美文网首页
网络请求 多线程 NSThread 锁

网络请求 多线程 NSThread 锁

作者: 弹吉他的少年 | 来源:发表于2018-08-31 17:47 被阅读0次

200 代表成功
404 文件不存在

  • 使用到http://网络的时候都需要在Info.plist加这么一个Key,加的时候箭头向下表示加在这里面:
  • 在线json转码工具

转码JSON当中乱码的网址

  • 线程当中使用self(弱引用)
__weak typeof(self) weakSelf = self;

GCD

这篇文章总结的比较细致
地址:https://www.jianshu.com/p/6e73cf6b485d


NSThread多线程

  • 创建一个子线程
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(increaseProgress) object:nil]; 
  • 有的时候app的启动页会一闪而过,如果想让启动页画面停留一会再启动应用,可以使用如下方式
    在AppDelegate的方法
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
   // 添加如下方法,将主线程暂停几秒钟
   [NSThread sleepForTimeInterval:1.0];//设置启动页面时间
}
  • 打印当前正在运行的线程
NSLog(@"main thread:%@",[NSThread currentThread]); 
  • 后台运行的方法:
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg {

}
  • 停止操作:
    先调用cancel方法把cancelled设置为YES,再
if ([[NSThread currentThread] isCancelled]) break; // 停止
  • 开一个线程,把一些耗时间的操作可以放里面执行
- (IBAction)doSomething:(NSThread *)sender {
 for (NSInteger i = 0; i < 10111111; i++) {
 if ([[NSThread currentThread] isCancelled]) break; // 停止
 NSLog(@"%ld", i);
 }
}

- (IBAction)buttonAction:(UIButton *)sender {
 // 直接开始线程里面的工作
 // [NSThread detachNewThreadSelector:@selector(threadSelector:) toTarget:self withObject:nil];
 // 需要调用start方法才开始
 myThread_ = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];    
 [myThread_ start]; // 开始
}

- (IBAction)cancelAction:(UIButton *)sender {
 [myThread_ cancel]; // 把cancelled设置为YES
}

1、同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作,

2、异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然可以对UI进行操作,程序可以继续运行

3、GET请求,将参数直接写在访问路径上。操作简单,不过容易被外界看到,安全性不高,地址最多255字节;

4、POST请求,将参数放到body里面。POST请求操作相对复杂,需要将参数和地址分开,不过安全性高,参数放在body里面,不易被捕获。

1、 同步GET请求

//第一步,创建URL
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];

//第二步,通过URL创建网络请求
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];

//NSURLRequest初始化方法第一个参数:请求访问路径,第二个参数:缓存协议,第三个参数:网络请求超时时间(秒)
其中缓存协议是个枚举类型包含:
NSURLRequestUseProtocolCachePolicy(基础策略)
NSURLRequestReloadIgnoringLocalCacheData(忽略本地缓存)
NSURLRequestReturnCacheDataElseLoad(首先使用缓存,如果没有本地缓存,才从原地址下载)
NSURLRequestReturnCacheDataDontLoad(使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作)
NSURLRequestReloadIgnoringLocalAndRemoteCacheData(无视任何缓存策略,无论是本地的还是远程的,总是从原地址重新下载)
NSURLRequestReloadRevalidatingCacheData(如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载)

//第三步,连接服务器
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

NSString *str = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
NSLog(@"%@",str);

2、同步POST请求

//第一步,创建URL
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"];

//第二步,创建请求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@"POST"];//设置请求方式为POST,默认为GET
NSString *str = @"type=focus-c";//设置参数
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];

//第三步,连接服务器
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
NSLog(@"%@",str1);

3、异步GET请求

//第一步,创建url
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];

//第二步,创建请求
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];

//第三步,连接服务器
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];

4、异步POST请求

//第一步,创建url
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"];

//第二步,创建请求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@"POST"];
NSString *str = @"type=focus-c";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];

//第三步,连接服务器
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];

5、异步请求的代理方法

//接收到服务器回应的时候调用此方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%@",[res allHeaderFields]);
self.receiveData = [NSMutableData data];
}
//接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[self.receiveData appendData:data];
}
//数据传完之后调用此方法
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSString *receiveStr = [[NSString alloc]initWithData:self.receiveData encoding:NSUTF8StringEncoding];
NSLog(@"%@",receiveStr);
}
//网络请求过程中,出现任何错误(断网,连接超时等)会进入此方法
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(@"%@",[error localizedDescription]);
}

1.创建NSURLSessionData网络请求

// 转码(有的web不支持中文)
 NSString *urlString = @"http://wthrcdn.etouch.cn/weather_mini?city=成都";
 NSString *encodeUrlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

 // 构建请求对象Request
 NSURL *url = [NSURL URLWithString:encodeUrlString];
 NSURLRequest *request = [NSURLRequest requestWithURL:url];

 // 构建Session的configuration
 NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

 // 构建NSURLSession(需要包含协议NSURLSessionDelegate)
 NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];

 // 得到Task对象
 NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
 NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

 // 解决字典中得乱码
 // NSLog(@"%@", jsonDict);
 // 打印出最高温最低温(根据jsonDict字典当中的键去取对应的值)
 NSDictionary *dataDict = [jsonDict objectForKey:@"data"];
 NSArray<NSDictionary*> *forecastDict = [dataDict objectForKey:@"forecast"];
 for (NSInteger i = 0; i < forecastDict.count; i++) {
 NSLog(@"日期为%@,%@,%@", [forecastDict[i] objectForKey:@"date"],[forecastDict[i] objectForKey:@"high"], [forecastDict[i] objectForKey:@"low"]);
 }

// NSString *json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// NSLog(@"%@", json);
 }];

 [dataTask resume]; // 恢复dataTask

2.创建NSURLSessionDownloadTask网络请求

// 防呆设计,规定按钮的状态
- (void) Start: (BOOL)start Pause:(BOOL)pause Resume:(BOOL)resume {

 // 设置按钮状态
 self.startButton.enabled = start;
 self.pauseButton.enabled = pause;
 self.resumeButton.enabled = resume;
}

// 设置图片地址
//#define URL @"[https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png](https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png)"

#define URL @"http://p1.pichost.me/i/40/1639665.png"

 // 创建请求对象
 NSString *encodeUrlString = [URL stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; // 转码(有的web不支持中文)

 NSURL *url = [NSURL URLWithString:encodeUrlString];

 NSURLRequest *request = [NSURLRequest requestWithURL:url];

 // 创建会话配置对象

 NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

 // 创建会话对象(需要包含协议NSURLSessionDelegate)

 session_ = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

 // 获取dowloadTask对象

 task_ = [session_ downloadTaskWithRequest:request];

 [task_ resume]; // 恢复task

 [self Start:NO Pause:YES Resume:NO];

}

// 下载过来以后调用的方法(必须实现的协议方法)

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {

 // 把URL转化为本地路径

 // 将下载的文件拷贝到/Liberary/Preferences目录

 NSFileManager *fileManager = [NSFileManager defaultManager];

 NSURL *liberaryURL = [fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask][0]; // 追加路径

 NSURL *preferencesURL = [liberaryURL URLByAppendingPathComponent:@"Preferences"];

 NSURL *desURL = [preferencesURL URLByAppendingPathComponent:[location lastPathComponent]];

 // 拷贝路径

 [fileManager removeItemAtURL:desURL error:nil];// 如果之前有,就删除原文件

 [fileManager copyItemAtURL:location toURL:desURL error:nil];

 // 显示到imageView里

 // 页面显示在主线程当中做

 dispatch_async(dispatch_get_main_queue(), ^{

 // 获得路径

 UIImage *image = [UIImage imageWithContentsOfFile:[desURL path]];

 // 把图片显示在imageView

 self.imageView.image = image;

 self.imageView.contentMode = UIViewContentModeScaleAspectFit;

 });

 NSLog(@"%@", location);

}

// 暂停当前下载

- (IBAction)pauseButtonAction:(UIButton *)sender {

 [task_ cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

 resumeData_ = resumeData; // 保存下载好的数据

 }];

 // 更新按钮状态

 [self Start:NO Pause:NO Resume:YES];

}

// 继续下载

- (IBAction)ResumeButtonAction:(UIButton *)sender {

 task_ = [session_ downloadTaskWithResumeData:resumeData_];

 [task_ resume];// 开始task

 // 更新按钮状态

 [self Start:NO Pause:YES Resume:NO];

}

// 获取下载的信息

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {

 NSLog(@"-----------------------------");

 // downloadTask每个包的大小

 NSLog(@"%lld", bytesWritten);

 // totalBytesWritten已下载的大小

 NSLog(@"%lld", totalBytesWritten);

 // totalBytesExpectedToWrite 总的大小

 NSLog(@"%lld", totalBytesExpectedToWrite);

 NSLog(@"-----------------------------");

 // 界面显示的在主线程当中做

 dispatch_async(dispatch_get_main_queue(), ^{

 // 进度条显示下载进度

 self.progressView.progress = (double)totalBytesWritten / totalBytesExpectedToWrite;

 });
}

NSThread

1. 创建

1.1 类方法

  • detachNewThreadSelector:toTarget:withObject:

类方法创建的线程会在创建后立即开始执行

例如:

[NSThread detachNewThreadSelector:@selector(sellTicket) toTarget:self withObject:nil];

1.2 实例方法

  • initWithTarget:selector:object:

实例方法创建的线程要在调用start方法后才开始执行,在其间我们可以对齐做一些设置

例如:

thread1_ = [[NSThread alloc] initWithTarget:self selector:@selector(sellTicket) object:nil];

[thread1_ setName:@"售票员1"];

[thread1_ start];

1.3 类别方法(隐式创建)

  • performSelectorInBackground:withObject:

和类方法类似,创建后立即执行

2. 常用的接口

2.1 让主线程执行某个方法

  • performSelectorOnMainThread:withObject:waitUntilDone:

2.2 结束线程

  • 当线程方法执行完毕后,会结束线程。
  • 调用线程的cancel方法。cancel方法会设置线程的cancelled属性值,我们需要在线程方法中足够多的地方判断cancelled属性值,如果为YES则退出线程方法。

3. 线程同步与锁

3.1 线程同步

同步就是协同步调,按预定的先后次序执行

3.2

在多线程编程里面,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术(加锁),保证数据在任何时刻,最多有一个线程访问,以保证数据的完整性。

3.3 锁的实现

3.3.1 @synchronized

只有相同的object才会互斥,不同的object不会互斥

@synchronized (object) {

// 执行的代码

}

3.3.2 NSLock

创建

NSLock *lock = [[NSLock alloc] init];

加锁与解锁

[lock_ lock];

// 执行的代码

[lock_ unlock];

3.3.3 其它遵循NSLocking协议的锁

  • NSConditionLock
  • NSRecursiveLock
  • NSDistributedLock

参看:Objective-C中不同方式实现锁()

相关文章

  • 网络请求 多线程 NSThread 锁

    200 代表成功404 文件不存在 使用到http://网络的时候都需要在Info.plist加这么一个Key,加...

  • iOS面试之多线程模块

    多线程 多线程内容如下: GCD NSOperation NSThread 多线程与锁 1.GCD 同步/异步和串...

  • iOS开发之多线程(一)

    目录 概要 NSThread GCD NSOperation 多线程与锁 1.概要 进程 线程 多线程 多线程的原...

  • iOS开发经验(19)-多线程

    目录 pthread NSThread GCD NSOperation 线程锁 线程通讯 | 多线程实现方案 ...

  • [iOS面试]第6章 多线程相关面试问题

    本文主讲多线程相关面试问题:包括GCD、NSOperation、NSThread、多线程与锁。 一、GCD 同步/...

  • iOS面试之多线程大全

    多线程 多线程内容如下: GCD NSOperation NSThread 多线程与锁 1.GCD 作为一个开发者...

  • GCD的使用和原理

    在我们做iOS开发的过程中,经常会与多线程打交道,异步绘制,网络请求等,方式有NSThread,NSOperati...

  • 多线程

    GCD NSOperation NSThread 多线程与锁 一、GCD 同步、异步 和 串行、并发 dispat...

  • iOS多线程篇:NSThread

    iOS多线程篇:NSThread iOS多线程篇:NSThread

  • 多线程

    ios中为我们提供了GCD、NSOpration、NSThread 一、GCD多线程与锁GCD 同步异步、串行、并...

网友评论

      本文标题:网络请求 多线程 NSThread 锁

      本文链接:https://www.haomeiwen.com/subject/lblewftx.html