2016-02-17 09:30:16 youyisg 阅读数 1710

最近用lame将ios录制语音转换成MP3时,播放时间变短,在iOS端是好的,到android时,时长变短。
后来发现是录音时和转码时的配置问题,以下是我的配置

录音时

NSURL* fileUrl = [NSURL fileURLWithPath:self.filePath];
        NSDictionary * soundSetting;
        soundSetting = [NSDictionary dictionaryWithObjectsAndKeys:
                        [NSNumber numberWithFloat:8000.0f],AVSampleRateKey,
                        [NSNumber numberWithInt:2],AVNumberOfChannelsKey,
                        [NSNumber numberWithInt:AVAudioQualityHigh],AVEncoderAudioQualityKey,
                        [NSNumber numberWithInt:16],AVEncoderBitRateKey,
                        nil];

        NSError* error;
        self.audioRecorder = [[AVAudioRecorder alloc]initWithURL:fileUrl settings:soundSetting error:&error ];
//开始录音
 AVAudioSession * audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [audioSession setActive:YES error:nil];

    [self.audioRecorder record];
//............
//停止录音
  if ([self.audioRecorder isRecording]) {
        [self.audioRecorder stop];
    }
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];  //此处需要恢复设置回放标志,否则会导致其它播放声音也会变小
    [session setActive:YES error:nil];

以下是转码时的配置


+(void)cafFile:(NSString *)cafFileName toMp3File:(NSString* )mp3FileName{
    @try {
        NSString* cafFilePath = [[PVConfig getAudioTempPath] stringByAppendingPathComponent: cafFileName] ;
        NSString* mp3FilePath = [[PVConfig getAudioPath] stringByAppendingPathComponent: mp3FileName];


        int read, write;

        FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");
        fseek(pcm, 4*1024, SEEK_CUR);//去除多余的头部,不然会有咔嚓的一声噪音
        FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb");

        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];

        lame_t lame = lame_init();
        lame_set_num_channels(lame, 2);//设置1为单通道,默认为2双通道
        lame_set_in_samplerate(lame, 8000.0);//11025.0
        //lame_set_VBR(lame, vbr_default);
        lame_set_brate(lame, 16);
        lame_set_mode(lame, 3);
        lame_set_quality(lame, 2); /* 2=high 5 = medium 7=low 音质*/
        lame_init_params(lame);

        do{
            read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0) {
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            }else{
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            }

            fwrite(mp3_buffer, write, 1, mp3);


        }while (read!=0);

        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
        NSLog(@"convert to mp3 succ %@",mp3FileName);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }



}

用这两个相对应的配置语音录制完成后播放时长就是对的了。

两个关键的地方

soundSetting = [NSDictionary dictionaryWithObjectsAndKeys:
                        [NSNumber numberWithFloat:8000.0f],AVSampleRateKey,
                        [NSNumber numberWithInt:2],AVNumberOfChannelsKey,
                        [NSNumber numberWithInt:AVAudioQualityHigh],AVEncoderAudioQualityKey,
                        [NSNumber numberWithInt:16],AVEncoderBitRateKey,
                        nil];

lame_set_num_channels(lame, 2);//设置1为单通道,默认为2双通道
        lame_set_in_samplerate(lame, 8000.0);//11025.0
        //lame_set_VBR(lame, vbr_default);
        lame_set_brate(lame, 16);
        lame_set_mode(lame, 3);
        lame_set_quality(lame, 2); /* 2=high 5 = medium 7=low 音质*/
2019-06-05 14:12:39 bitcser 阅读数 84
UIViewController *rootVC = self.presentingViewController; 
while (rootVC.presentingViewController) { 
    rootVC = rootVC.presentingViewController; 
} 
[rootVC dismissViewControllerAnimated:YES completion:nil];

多级返回,适用于A->B  B->C    C直接返回A

2017-11-10 15:20:20 freekiteyu 阅读数 1624

iOS 入门简介

概述

iOS(原名 iPhone OS,自 iOS 4 后改名为 iOS)是苹果公司为移动设备所开发的专有移动操作系统,所支持的设备包括 iPhone、iPod touch 和 iPad。与 Android 不同,iOS 不支持任何非苹果的硬件设备。

iOS 是由苹果公司开发的移动操作系统。苹果公司最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。最初苹果公司并没有给随 iPhone 发行的 iOS 一个独立的称谓,直到 2008 年才取名为 iPhone OS,并在 2010 年 6 月改名为 iOS。2012 年发布四英寸设备 iPhone 5,从此开启多屏幕适配的道路。WWDC 2013 中,苹果发布了 iOS 7,彻底更改了用户界面,将原本拟物的风格转变为平面化风格。

  • 2007:第一个 iOS 版本,提出为它提供软件支持。iPhone 1 上市。
  • 2008:操作系统系统取名为 iPhone OS,AppStore 出现。iPhone 3G 上市。
  • 2009:iPhone OS 3 发布,增加复制粘贴,Spotlight 搜索和语音控制等,拟物化设计。iPhone 3GS 上市。
  • 2010:iPhone OS 改名为 iOS,增加双击 Home 键跳转应用。iPhone 4 上市。
  • 2011:iOS 5 发布,增加 iCloud,新的 iMessage 和通知中心。iPhone 4s 上市。
  • 2012:iOS 6 发布,增加自己的地图服务。iPhone 5 上市。
  • 2013:iOS 7 发布,扁平化设计,增加 Touch ID 允许通过指纹识别来解锁设备。iPhone 5c/5s 上市。
  • 2014:iOS 8 发布,增加在 Mac 上也可以阅读和编辑 iMessages,或者接听电话。iPhone 6/6 plus 上市。
  • 2015:iOS 9 发布。iPhone 6s/6s plus 上市。
  • 2016:iOS 10 发布,增加家庭 App,通知可直接显示图片和视频。iPhone SE/7/7 plus 上市。
  • 2017:iOS 11 发布,增加对 AR 的支持,提供 ARKit。iPhone X/8/8 plus 上市。
  • ……

系统架构

ios_system_level

iOS 系统分为可分为四级结构,由上至下分别为可触摸层(Cocoa Touch Layer)、媒体层(Media Layer)、核心服务层(Core Services Layer)、核心系统层(Core OS Layer),每个层级提供不同的服务。低层级结构提供基础服务如文件系统、内存管理、I/O 操作等。高层级结构建立在低层级结构之上提供具体服务如 UI 控件、文件访问等。

iOS 8.3 系统框架架构图

ios_8_system_level_desc

  • 可触摸层(Cocoa Touch Layer)

大部分与用户界面有关,本质上来说它负责用户在 iOS 设备上的触摸交互操作。这一层基本都是基于 Objective-C 的接口。

可触摸层主要提供用户交互相关的服务如界面控件、事件管理、通知中心、地图,包含以下框架:

  • UIKit(界面相关)
  • EventKit(日历事件提醒等)
  • Notification Center(通知中心)
  • MapKit(地图显示)
  • Address Book(联系人)
  • iAd(广告)
  • Message UI(邮件与 SMS 显示)
  • PushKit(iOS8 新 push 机制)
  • 媒体层(Media Layer)

通过它我们可以在应用程序中使用各种媒体文件,进行音频与视频的录制,图形的绘制,以及制作基础的动画效果。这一层既有基于 Objective-c 的接口也有基于 C 语言的接口。

媒体层主要提供图像引擎、音频引擎、视频引擎框架:

  • 图像引擎(Core Graphics、Core Image、Core Animation、OpenGL ES)
  • 音频引擎 (Core Audio、 AV Foundation、OpenAL)
  • 视频引擎(AV Foundation、Core Media)
  • 核心服务层(Core Services Layer)

可以通过它来访问 iOS 的一些服务。基本都是基于 C 语言的接口。

核心服务层为程序提供基础的系统服务例如网络访问、浏览器引擎、定位、文件访问、数据库访问等,主要包含以下框架:

  • CFNetwork(网络访问)
  • Core Data(数据存储)
  • Core Location(定位功能)
  • Core Motion(重力加速度,陀螺仪)
  • Foundation(基础功能如 NSString)
  • Webkit(浏览器引擎)
  • JavaScript(JavaScript 引擎)
  • 核心系统层(Core OS Layer)

它包括内存管理、文件系统、电源管理以及一些其他的操作系统任务。它可以直接和硬件设备进行交互。作为 App 开发者不需要与这一层打交道。基本都是基于 C 语言的接口。核心系统层提供为上层结构提供最基础的服务如操作系统内核服务、本地认证、安全、加速等。

操作系统内核服务(BSD sockets、I/O 访问、内存申请、文件系统、数学计算等)
本地认证(指纹识别验证等)
安全(提供管理证书、公钥、密钥等的接口)
加速 (执行数学、大数字以及 DSP 运算,这些接口 iOS 设备硬件相匹配)

在上面所有的框架中,最重要也最经常使用的就是 UIKit 和 Foundation 框架。

Foundation 框架提供许多基本的对象类和数据类型,使其成为应用程序开发的基础,为所有应用程序提供最基本的系统服务,和界面无关。

UIKit 框架提供的类是基础的UI类库,用于创建基于触摸的用户界面,所有 iOS 应用程序都是基于 UIKit,它提供应用程序的基础架构,用于构建用户界面,绘图、处理和用户交互事件,响应手势等等。UIKit 通过控制器对象管理屏幕上显示的内容,界面的跳转,来组织应用程序。没有 UIKit 框架就没有 iOS 应用程序。

开发准备

参考资料

我的公众号

欢迎你「扫一扫」下面的二维码,关注我的公众号,可以接受最新的文章推送,有丰厚的抽奖活动和福利等着你哦!?

如果你有什么疑问或者问题,可以 点击这里 提交 issue,也可以发邮件给我 jeanboy@foxmail.com

同时欢迎你 Android技术进阶:386463747 来一起交流学习,群里有很多大牛和学习资料,相信一定能帮助到你!

2016-07-12 11:45:57 tie343918860 阅读数 654

可以直接使用CAGradientLayer来实现渐变色。(android有各种drawable,iOS有各种layer。)

http://blog.sina.com.cn/s/blog_a0a07e4f0102w5jb.html

http://www.jianshu.com/p/c780bbd14091

http://blog.csdn.net/lwq421336220/article/details/8179650

http://blog.csdn.net/xunyn/article/details/30727863

2018-12-19 19:01:42 Bolted_snail 阅读数 597

  • 最近公司项目安全检查检测到缓存中的用户名和密码,虽然已经加密,但还是不安全;所以公司要求用cookie或者token去请求数据。由于公司项目比较老,里面既用了ASIHTTPRequest框架,又用了AFNetworking框架,发现其实这两个框架默认都是自动保持cookie的,我们不用去刻意处理它(获取与上传)。但是由于想搞清楚还是研究了一下cookie,并用NSURLSessionASIHTTPRequestAFNetworking自己手动管理cookie
  • cookie: 是网站服务端为了辩别用户身份,在服务器端生生成并存储在用户本地终端(电脑、手机)上的数据。其实cookie主要是用来免密登录的,我们这只是通过用户名和密码获取一个身份令牌,用于后面的接口调用,更像是token

NSHTTPCookieStorage 管理cookie

  • NSHTTPCookieStorage提供了管理所有NSHTTPCookie对象的接口,在OS X里,cookie是在所有程序中共享的,而在iOS中,cookie只在当当前应用中有效。。Session Cookie(SessionOnly返回YES的Cookie)只能在单一进程中使用。

NSHTTPCookieStorage和NSHTTPCookie关系

  • NSHTTPCookieStorage可以获取,删除,设置单例里面的cookies,设置cookie的管理策略等。
//只读的单例对象
@property(class, readonly, strong) NSHTTPCookieStorage *sharedHTTPCookieStorage;
//获取里面的cookie对象数组
@property (nullable , readonly, copy) NSArray<NSHTTPCookie *> *cookies;
//添加cookie
- (void)setCookie:(NSHTTPCookie *)cookie;
//删除cookie
- (void)deleteCookie:(NSHTTPCookie *)cookie;
//删除某个日期之前的cookie
- (void)removeCookiesSinceDate:(NSDate *)date API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
//设置cookie的管理策略
@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;
//获取对应url返回的cookie数组
- (nullable NSArray<NSHTTPCookie *> *)cookiesForURL:(NSURL *)URL;
  • NSHTTPCookie里面有个properties的属性,其组成如下:
<__NSArrayM 0x283bec540>(
<NSHTTPCookie
	version:0
	name:JSESSIONID
	value:A0787301B667F5E1C7B5BABAAE58B104
	expiresDate:'(null)'
	created:'2018-12-27 02:39:06 +0000'
	sessionOnly:TRUE
	domain:192.168.1.121
	partition:none
	sameSite:none
	path:/inner
	isSecure:FALSE
	isHTTPOnly: YES
 path:"/inner" isSecure:FALSE isHTTPOnly: YES>,
<NSHTTPCookie
	version:0
	name:token
	value:1545878346436_111_cd90cdd1-9938-4e18-8ccd-79ad54d5527c
	expiresDate:'2019-01-26 02:39:06 +0000'
	created:'2018-12-27 02:39:06 +0000'
	sessionOnly:FALSE
	domain:192.168.1.121
	partition:none
	sameSite:none
	path:/inner
	isSecure:FALSE
 path:"/inner" isSecure:FALSE>
)
name 必选 规定 cookie 的名称
value 必选 规定 cookie 的值
expire 可选 规定 cookie 的有效期
path 可选 规定 cookie 的服务器路径,只有该路劲下的文件接口才能使用
domain 可选 规定 cookie 的域名
secure 可选 规定是否通过安全的 HTTPS 连接来传输 cookie

其中sessionOnly:TRUE的cookie是后台服务器自动创建的。

  • cookiesession默认都是后台创建,后端会将cookie放在在responseheader中返回给前端,将session缓存在服务器中;前端获取到cookie可以自己手动保存,也可以交给NSHTTPCookieStorage单例来保存;前端将cookie放在requestheader中传给服务器,服务器会去查对应的session,然后去交换获得用户信息(用户登录ID等)请求接口,这就是整个cookie获取、设置和请求数据的流程。
  • 获取cookie的几种方法:
 //方式1 :  NSHTTPCookie获取cookie
               NSArray * array = [NSHTTPCookie cookiesWithResponseHeaderFields:httpresponse.allHeaderFields forURLresponse.URL];
                for (NSHTTPCookie * cookie in array) {
                    //保存到sharedHTTPCookieStorage中
                    [[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookie:cookie];
                }
                
//方式2:NSHTTPURLResponse获取
NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response;
                NSDictionary * dic = httpresponse.allHeaderFields;
                //获取cookie字符串
                NSString * cookiesStr = [dic valueForKey:@"Set-Cookie"];
                
//方式3:NSHTTPCookieStorage获取cookie
NSArray * cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];
  • 多个cookie的格式通常为:cookie1=value1; cookie2=value2; cookie3=value3; 这里特别要注意,多个cookie之间用分号+空格分隔开,不是&也不是单纯的空格。我所了解到的iOS设置Cookie的方法有两种。
    设置cookie方式1:NSDictionary * dic = httpresponse.allHeaderFields;返回的字典有个"Set-Cookie"的字符串值就是多个cookie的默认样式,我们获取到后可以直接设置cookierequest的 header中。
{
    "Cache-Control" = "no-cache,must-revalidate";
    "Content-Length" = 7;
    Date = "Thu, 27 Dec 2018 07:11:51 GMT";
    Expires = "Thu, 01 Jan 1970 00:00:00 GMT";
    Pragma = "no-cache";
    Server = "Apache-Coyote/1.1";
    "Set-Cookie" = "JSESSIONID=D6F65DA599B3B6B22C1927C5D85B53F0; Path=/inner; HttpOnly, token=1545894711778_111_17906b71-9c77-48c5-8e5a-b9e52522a538; Expires=Sat, 26-Jan-2019 07:11:51 GMT; Path=/inner";
}
NSString * cookiesStr = [dic valueForKey:@"Set-Cookie"];
//设置cookies
 [request setValue:cookiesaStr forHTTPHeaderField:@"Cookie"];

设置cookie方式2:构建多个NSHTTPCookie实例对象的数组,根据NSHTTPCookie实例数组生成对应的HTTP cookie header,设置cookierequestheader中。

NSDictionary *properties1 = [NSDictionary dictionaryWithObjectsAndKeys:
                                @"domain.com", NSHTTPCookieDomain,
                                @"/", NSHTTPCookiePath,
                                @"userid", NSHTTPCookieName,
                                strUserId, NSHTTPCookieValue,
                                nil];
    
    NSDictionary *properties2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                 @"domain.com", NSHTTPCookieDomain,
                                 @"/", NSHTTPCookiePath,
                                 @"pid", NSHTTPCookieName,
                                 pid, NSHTTPCookieValue,
                                 nil];
    
    
    NSHTTPCookie *cookie1 = [NSHTTPCookie cookieWithProperties:properties1];
    NSHTTPCookie *cookie2 = [NSHTTPCookie cookieWithProperties:properties2];
    NSArray* cookies = [NSArray arrayWithObjects: cookie1, cookie2, nil];
    //根据NSHTTPCookie实例数组生成对应的HTTP cookie header
    NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
    //设置cookie到header中
    request.allHTTPHeaderFields = headers; 

NSURLSession管理cookie

  • NSURLSession中有两个+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;初始化方法,这个configuration可以给NSURLSession实例对象配置一下属性策略等,与cookie有关的属性有下:
//发送请求时是否设置cookie
@property BOOL HTTPShouldSetCookies;
//设置cookie的接收策略
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;
typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {
    NSHTTPCookieAcceptPolicyAlways,//接收所有的cookie,默认策略.
    NSHTTPCookieAcceptPolicyNever,//不接收所有的cookie
    NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain//只接收main document domain中的cookie.
};
//保存设置cookie的,如果不设置默认是[NSHTTPCookieStorage sharedHTTPCookieStorage],设置为nil管理cookie
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;

所以NSURLSession多了一种设置cookie的方式,只要设置了HTTPCookieStorage属性就可以自动设置了cookie。

1.使用系统管理cookie的类NSHTTPCookieStorage管理cookie

我们请求完成后必须手动将cookie保存到[NSHTTPCookieStorage sharedHTTPCookieStorage]中,不会自动将响应体header中的cookie保存,下面是具体实例。

//获取cookie
- (void)getCookies1{
    NSURL * url = [NSURL URLWithString:@"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!login.action?"];
    NSString * post = [NSString stringWithFormat:@"loginId=%@",@"111"];
    NSData * postData = [post dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBody = postData;
    //defaultSessionConfiguration 使用默认session配置,类似NSURLConnection的标准配置,使用硬盘来存储缓存数据,会将缓存、cookie等存在本地
    //ephemeralSessionConfiguration 临时session配置,与默认配置相比,不使用永久持存cookie、证书、缓存的配置,最佳优化数据传输。
    //backgroundSessionConfiguration 后台session配置,与默认配置类似,不同的是会在后台开启另一个线程来处理网络数据
    NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    //不允许设置cookie
    defultConfiguration.HTTPShouldSetCookies = NO;
    //设置不允许缓存cookiechelue
    defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
    //清除所有的cookie
    for(NSHTTPCookie *cookie in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies)
    {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie: cookie];
   }
     NSLog(@"清除所有的cookies : %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);
    defultConfiguration.HTTPCookieStorage = nil;
    NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];
    NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"请求完成!!!");
        if (!error) {
            NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            if (result) {
                NSLog(@"解析成功:%@",result);
                NSLog(@"response:%@",response);
                NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response;
                NSDictionary * dic = httpresponse.allHeaderFields;
//                NSString * cookies = [dic valueForKey:@"Set-Cookie"];
//                NSLog(@"cookies : %@ --- %@",cookies,[NSThread currentThread]);
//                NSArray * NSArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];
                //获取cookie
               NSArray * array = [NSHTTPCookie cookiesWithResponseHeaderFields:dic forURL:response.URL];
                for (NSHTTPCookie * cookie in array) {
                    //保存到sharedHTTPCookieStorage中
                    [[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookie:cookie];
                }
               NSLog(@"NSHTTPCookieStorage :  %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);
                
            }else{
                NSLog(@"解析失败!!!");
            }
        }else{
            NSLog(@"请求失败 : %@",error.localizedDescription);
        }
    }];
    [task resume];
}

//设置cookie
- (void)requestWithCookies1{
    NSString * urlStr = @"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!getData.action?";
    //encode去掉中午和特殊字符
    urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL * url = [NSURL URLWithString:urlStr];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    defultConfiguration.HTTPShouldSetCookies = YES;
    defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
    NSLog(@"NSHTTPCookieStorage :  %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);
    defultConfiguration.HTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];
    NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"请求完成!!!");
        if (!error) {
            NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            if (result) {
                NSLog(@"解析成功:%@",result);
            }else{
                NSLog(@"解析失败!!!");
            }
        }else{
            NSLog(@"请求失败 : %@",error.localizedDescription);
        }
    }];
    [task resume];
}

2.自己手动管理cookie

上面的方法有时候并不能立即将cookie设置进去,所以我们自己手动管理cookie比较保险,就是在requestheader中设置cookie,在responseheader中获取到得cookie保存到偏好设置或单例中自己管理。

//获取cookie
- (void)getCookies2{
    NSURL * url = [NSURL URLWithString:@"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!login.action?"];
    NSString * post = [NSString stringWithFormat:@"loginId=%@",@"111"];
    NSData * postData = [post dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBody = postData;
    NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    //不允许设置cookie
    defultConfiguration.HTTPShouldSetCookies = NO;
    //不接受cookie
    defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
    
    NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];
    NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"请求完成!!!");
        if (!error) {
            NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            if (result) {
//                NSArray * cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];
                NSLog(@"解析成功:%@",result);
                NSLog(@"response:%@",response);
                NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response;
                NSDictionary * dic = httpresponse.allHeaderFields;
                //获取cookie字符串
                NSString * cookiesStr = [dic valueForKey:@"Set-Cookie"];
                NSData * cookiesData = [NSKeyedArchiver archivedDataWithRootObject:cookiesStr];
                //保存到偏好设置中
                [[NSUserDefaults standardUserDefaults] setValue:cookiesData forKey:@"BoncUserDefaultsCookie"];
                [[NSUserDefaults standardUserDefaults]synchronize];
            }else{
                NSLog(@"解析失败!!!");
            }
        }else{
            NSLog(@"请求失败 : %@",error.localizedDescription);
        }
    }];
    [task resume];
}


//设置cookie
- (void)requestWithCookies2{
    NSString * urlStr = @"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!getData.action?";
    //encode去掉中午和特殊字符
    urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL * url = [NSURL URLWithString:urlStr];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    NSData * cookiesData = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookie"];
    NSString * cookiesaStr = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
    //设置cookies
    [request setValue:cookiesaStr forHTTPHeaderField:@"Cookie"];
    //如果是NSURLRequest,可用下面方式设置
//    request.allHTTPHeaderFields = nil;
    NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defultConfiguration.HTTPShouldSetCookies = NO;
    defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
    NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];
    NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"请求完成!!!");
        if (!error) {
            NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            if (result) {
                NSLog(@"解析成功:%@",result);
            }else{
                NSLog(@"解析失败!!!");
            }
        }else{
            NSLog(@"请求失败 : %@",error.localizedDescription);
        }
    }];
    [task resume];
}

AFNetworking自己管理cookie

  • AFNetworking是自动保持cookie的,我们不用去刻意处理它(获取与上传),除非你有一些需要。这里要讲的是我们手动管理cookieAFNetworking中并没有专门为cookie封装的代码,不过底层使用的是NSURLRequest,所以我们可以获取到请求时服务器返回的cookie,然后保存起来(删除和保存由我们自己管理),请求时候设置到requestheader中即可。
  • 设置不保持cookie
//默认是YES,cookie会被存储在共享的 NSHTTPCookieStorage 容器中
_manager.requestSerializer.HTTPShouldHandleCookies = NO;
  • 获取cookie,并保存起来
      // 获取所有数据报头信息
        NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)task.response;
        NSDictionary *fields = [HTTPResponse allHeaderFields];
        // 获取cookie
        NSString *cookieString = [fields valueForKey:@"Set-Cookie"];
        //保存到偏好设置中
        [[NSUserDefaults standardUserDefaults] setObject:cookieString forKey:@"BoncUserDefaultsCookie"];
        [[NSUserDefaults standardUserDefaults]synchronize];
  • 设置cookie
   NSString * cookie = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookie"];
    [self.manager.requestSerializer setValue:cookie forHTTPHeaderField:@"Cookie"];

ASIHTTPRequest自己管理cookie

  • ASIHTTPRequest是自动保持cookie的,如果我们所用cookie请求数据,默认情况下我们不需要做其他任何操作。不同于AFNetworking的是ASIHTTPRequestcookie进行了封装,不管是获取还是设置都及其方便,这里是我们自己管理cookie的做法。

  • 设置不保持cookie

//默认是YES,cookie会被存储在共享的 NSHTTPCookieStorage 容器中,并且会自动被其他request重用。
request.useCookiePersistence = NO;
//清空session期间创建的所有cookie
//[ASIFormDataRequest setSessionCookies:nil];
//清除session期间产生的所有的cookie和缓存的授权数据。
// [ASIFormDataRequest clearSession];
  • 获取和保存cookie:
 //获取cookie
 NSArray * cookies = [request responseCookies];
 //获取responseHeader
// NSDictionary *headers = [request responseHeaders];
 //保存cookie
 NSData * cookiesData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
 [[NSUserDefaults standardUserDefaults]setValue:cookiesData forKey:@"BoncUserDefaultsCookies"];
 [[NSUserDefaults standardUserDefaults]synchronize];
  • 设置cookie
    //依然要设置不保持cookie,否则传递cookie就不是我们自己保存到cookie
    [request setUseCookiePersistence:NO];
    //取出cookie
    NSData * cookiesData = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookies"];
    NSArray * cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
     //设置cookie
    [request setRequestCookies:cookies.mutableCopy];
  • AFNetworkingASIHTTPRequest默认都是开启cookie的,并且都是用[NSHTTPCookieStorage sharedHTTPCookieStorage]管理cookie的,所有二者可以通用,我们这里手动管理cookie,可以自己控制cookie的生命周期,避免过期的情况。其实默认情况已经够我们正常使用了,这里需要注意点是默认都是开启cookie的情况下,如在我们登录获取cookie时候,一定要先清除cookie,否则可能出现退出登录(不退出应用)换了个用户登录,登录后的数据还是上个用户的信息(未清除jsessionID),虽然可以交给后台取处理(后台判断是不是登录接口,如果是就不取cookie),但我们客户端也应该处理一下,避免该错误的发生。

AFNetworking请求登录接口时候清除cookie:

AFHTTPSessionManager  * manager =  [AFHTTPSessionManager manager];
[manager.requestSerializer setValue:nil forHTTPHeaderField:@"Cookie"];
//有时候这样设置并不好使,虽然也是在不保持cookie,但[NSHTTPCookieStorage sharedHTTPCookieStorage]还是保持了cookie,这样jsessionID并没有清除,所以为保险起见要清空[NSHTTPCookieStorage sharedHTTPCookieStorage]里面的cookies
- (void)clearCookies{
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *_tmpArray = [NSArray arrayWithArray:[cookieStorage cookies]];
    for (id obj in _tmpArray) {
        [cookieStorage deleteCookie:obj];
    }
}

ASIHTTPRequest请求登录接口时候清除cookie:

[ASIFormDataRequest setSessionCookies:nil];

UIWebView和WKWebView的cookie管理机制

  • UIWebView会将NSHttpRequest的所有请求产生的cookie自动保存到NSHTTPCookieStorage容器中,并且在同一个app内多个UIWebView之间共享,不需要我们做任何操作,在后续访问中会将 cookie 自动带到request 请求当中。

  • WKWebViewcookie问题在于 WKWebView发起的请求不会自动带上存储于 NSHTTPCookieStorage容器中的Cookie,实践发现WKWebView实例其实也会将cookie存储于 NSHTTPCookieStorage 中,但存储时机有延迟,在iOS 8上,当页面跳转的时候,当前页面的 cookie 会写入NSHTTPCookieStorage中,而在 iOS 10 上,JS 执行 document.cookie 或服务器 set-cookie注入的 cookie会很快同步到 NSHTTPCookieStorage中,在执行 [WKWebView loadReques:] 前将 NSHTTPCookieStorage中的内容复制到 WKHTTPCookieStore中,以此来达到 WKWebView cookie注入的目的。


iOS 下拉图片变大

阅读数 94

IOS 基础入门教程

阅读数 1326

没有更多推荐了,返回首页