200 代表成功
404 文件不存在
- 使用到
http://
网络的时候都需要在Info.plist
加这么一个Key,加的时候箭头向下表示加在这里面:
- 在线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
网友评论