首页 文章 精选 留言 我的

精选列表

搜索[ios],共10000篇文章
优秀的个人博客,低调大师

iOS消息转发小记

消息转发流程图 15277558865032.jpg 如果类接收到无法处理的消息,会触发消息转发机制,一共有三个步骤,接受者在每一步中均有机会处理消息。步骤越往后,处理消息的代价就越大,所以最好再第一步就处理完。 第一道防线 在类里面实现两个方法来处理未知消息。执行动态方法解析之前,先会判断是否曾经有动态解析。 resolveInstanceMethod:处理实例方法 resolveClassMethod:处理类方法 我们来看个Demo,先看调用方代码 TestA *testA = [[TestA alloc] init]; [testA instanceMethod]; [TestA classMethod]; 再来看看TestA的定义。 // TestA.h @interface TestA : NSObject - (void)instanceMethod; + (void)classMethod; @end // TestA.m @implementation TestA - (void)newInstanceMethod { NSLog(@"newInstanceMethod"); } + (void)newClassMethod { NSLog(@"newClassMethod"); } + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(instanceMethod)) { // 动态添加方法newInstanceMethod Method method = class_getInstanceMethod([self class], @selector(newInstanceMethod)); IMP imp = method_getImplementation(method); class_addMethod([self class], sel, imp, method_getTypeEncoding(method)); // 成功处理,消息转发机制结束,调用newInstanceMethod return YES; } // 不能处理,进入第二步 return [super resolveInstanceMethod:sel]; } + (BOOL)resolveClassMethod:(SEL)sel { if (sel == @selector(classMethod)) { // 动态添加方法newClassMethod Method method = class_getInstanceMethod(object_getClass(self), @selector(newClassMethod)); IMP imp = method_getImplementation(method); class_addMethod(object_getClass(self), sel, imp, method_getTypeEncoding(method)); // 成功处理,消息转发机制结束,调用newClassMethod return YES; } // 不能处理,进入第二步 return [super resolveClassMethod:sel]; } @end TestA中头文件定义了两个方法,但是没有实现,如果不用消息转发机制处理异常,会导致crash,log想必大家应该很熟悉 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TestA funcA]: unrecognized selector sent to instance 0x6040000125c0' 实例方法存储在类对象,类方法存储在元类对象,在调用class_addMethod时,第一个参数需要注意。 第二道防线 第二道防线依赖一个函数forwardingTargetForSelector。 // 类方法 //+ (id)forwardingTargetForSelector:(SEL)aSelector { // //} - (id)forwardingTargetForSelector:(SEL)aSelector { if (aSelector == @selector(instanceMethod)) { // 消息转发给TestB实例 return [TestB new]; } // 消息转发失败,进入下一步 return nil; } // TestB.m - (void)instanceMethod { NSLog(@"instanceMethod"); } 第三道防线 第三道防线有两步 调用methodSignatureForSelector,获取新的方法签名(返回值类型,参数类型) 调用forwardInvocation,转发消息, // 方法签名(返回值类型,参数类型) // 类方法减号改为加号 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature *signature = [TestB instanceMethodSignatureForSelector:aSelector]; return signature; } // NSInvocation封装了方法调用,包括:方法调用者、方法名、方法参数 // anInvocation.target 消息接受者 // anInvocation.selector 函数名 // [anInvocation getArgument:NULL atIndex:0]; 获取参数 // 类方法减号改为加号 - (void)forwardInvocation:(NSInvocation *)anInvocation { [anInvocation invokeWithTarget:[TestB new]]; }

优秀的个人博客,低调大师

iOS AFNetworking(网络框架)

AFNetworking NSURLConnection ---导入头文件"AFHTTPRequestOperationManager.h" 1. 发送GET请求 //发送get请求 - (void)get { [[AFHTTPRequestOperationManager manager] GET:@"http://127.0.0.1/demo.json" parameters:nil success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) { NSLog(@"%@",responseObject); NSLog(@"%@",[responseObject class]); } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } 2. 发送GET请求--带参数 //发送get请求,传参数 - (void)get { [[AFHTTPRequestOperationManager manager] GET:@"http://127.0.0.1/php/login.php" parameters:@{@"username":@"abc",@"password":@"123"} success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) { NSLog(@"%@",responseObject); } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } 3. 发送POST请求 //演示post请求 - (void)post { [[AFHTTPRequestOperationManager manager] POST:@"http://127.0.0.1/php/login.php" parameters:@{@"username":@"abcd",@"password":@"lalala"} success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) { NSLog(@"%@",responseObject); } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } 4. 上传文件 - (void)post { //获取要上传文件的路径 NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"06.jpg" withExtension:nil]; NSURL *url2 = [[NSBundle mainBundle] URLForResource:@"01.jpg" withExtension:nil]; [[AFHTTPRequestOperationManager manager] POST:@"http://127.0.0.1/php/upload/upload-m.php" parameters:@{@"username":@"zhangsan"} constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { //上传文件 [formData appendPartWithFileURL:url1 name:@"userfile[]" error:nil]; [formData appendPartWithFileURL:url2 name:@"userfile[]" error:nil]; } success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) { NSLog(@"%@",responseObject); } failure:^(AFHTTPRequestOperation * _Nullable operation, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } NSURLSession ---导入头文件"AFHTTPSessionManager.h" 1. 发送GET请求 - (void)get { [[AFHTTPSessionManager manager] GET:@"http://127.0.0.1/demo.json" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { NSLog(@"%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } 2. 下载任务 - (void)download { NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/abc.hm"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; //进度 NSProgress *progress = nil; [[[AFHTTPSessionManager manager] downloadTaskWithRequest:request progress:&progress destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { // NSLog(@"targetPath -- %@",targetPath); NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename]; // 本地文件的URL必须使用这种方式获取 NSURL *url = [[NSURL alloc] initFileURLWithPath:path]; //返回要保存文件的路径 return url; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { NSLog(@"%@",filePath); }] resume]; //观察progress的某个属性fractionCompleted(进度)是否发生变化 //KVO [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([object isKindOfClass:[NSProgress class]]) { // NSLog(@"%@",change); NSProgress *progress = object; NSLog(@"%@",progress.localizedDescription); NSLog(@"%@",progress.localizedAdditionalDescription); NSLog(@"completedUnitCount : %zd",progress.completedUnitCount); NSLog(@"totalUnitCount : %zd",progress.totalUnitCount); NSLog(@"fractionCompleted : %f",progress.fractionCompleted); //回到主线程更新UI NSLog(@"%@",[NSThread currentThread]); } } 3. 获取网页数据--修改默认的序列化器 - (void)getBaidu { AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //修改响应的序列化器 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; [manager GET:@"http://www.baidu.com" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { NSString *html = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; NSLog(@"%@",html); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } 4. 解析XML - (void)getXML { AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 设置序列号器为XML,也可修改为AFHTTPResponseSerializer,使用第三方框架解析二进制数据 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; [manager GET:@"http://127.0.0.1/videos.xml" parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, NSXMLParser *responseObject) { //解析xml responseObject.delegate = self; [responseObject parse]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@",error); }]; } //NSXMLParser 的代理方法 - (void)parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"1 开始解析"); } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict { NSLog(@"2 开始节点 %@ %@",elementName,attributeDict); } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"3 节点之间的内容 %@",string); } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"4 结束节点 %@",elementName); } - (void)parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"5 结束解析"); } - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { NSLog(@"6 错误"); }

优秀的个人博客,低调大师

iOS 上传多个文件

上传文件格式 POST /php/upload/upload.php HTTP/1.1 Host: 127.0.0.1 Content-Type: multipart/form-data; boundary=标识(可自定义) 请求体 --标识(可自定义,但必须与请求头中一致) Content-Disposition: form-data; name="userfile[]"; filename="head1.png" Content-Type: image/png 空行 文件二进制数据 --标识(可自定义,但必须与请求头中一致) Content-Disposition: form-data; name="userfile[]"; filename="head2.png" Content-Type: image/png 空行 文件二进制数据 --标识(可自定义,但必须与请求头中一致) Content-Disposition: form-data; name="字段名" 数据值 --标识(可自定义,但必须与请求头中一致)-- 多文件文件上传 #define kBOUNDARY @"abc" - (void)viewDidLoad { [super viewDidLoad]; // 网络链接 NSString *netUrl = @"http://127.0.0.1/php/upload/upload-m.php"; // 文件路径 NSString *path1 = [[NSBundle mainBundle] pathForResource:@"head1.png" ofType:nil]; NSString *path2 = [[NSBundle mainBundle] pathForResource:@"head2.png" ofType:nil]; NSArray *array = @[path1, path2]; // 字段名 NSString *fieldName = @"userfile[]"; // 数据字典 NSDictionary *dict = @{@"username":@"mazaiting"}; // 上传文件 [self uploadFiles:netUrl fieldName:fieldName filePaths:array params:dict]; } // 上传多个文件 // netUrl 网络链接 // fieldName 字段名 // filePaths 文件路径数组 // params 参数字典 - (void)uploadFiles:(NSString *)netUrl fieldName:(NSString *)fieldName filePaths:(NSArray *)filePaths params:(NSDictionary *)params { NSURL *url = [NSURL URLWithString:netUrl]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"post"; // Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJa8BALfIc9saou2X [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",kBOUNDARY] forHTTPHeaderField:@"Content-Type"]; request.HTTPBody = [self body:fieldName filePaths:filePaths params:params]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { if (connectionError) { NSLog(@"连接错误 %@", connectionError); return; } NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if (httpResponse.statusCode == 200 || httpResponse.statusCode == 304) { // 解析数据 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; NSLog(@"%@",dict); } else { NSLog(@"服务器内部错误"); } }]; } // 构建请求体 - (NSData *)body:(NSString *)fieldName filePaths:(NSArray *)filePaths params:(NSDictionary *)params { NSMutableData *mData = [NSMutableData data]; // ------WebKitFormBoundaryJa8BALfIc9saou2X // Content-Disposition: form-data; name="userfile[]"; filename="head1.png" // Content-Type: image/png // // 文件二进制数据 // ------WebKitFormBoundaryJa8BALfIc9saou2X // Content-Disposition: form-data; name="userfile[]"; filename="head2.png" // Content-Type: image/png // // 文件二进制数据 // ------WebKitFormBoundaryJa8BALfIc9saou2X // Content-Disposition: form-data; name="username" // // mazaiting // ------WebKitFormBoundaryJa8BALfIc9saou2X-- // 构建文件,遍历数组 [filePaths enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { // ------WebKitFormBoundaryJa8BALfIc9saou2X // Content-Disposition: form-data; name="userfile[]"; filename="head2.png" // Content-Type: image/png // // 文件二进制数据 NSMutableString *mString = [NSMutableString string]; // 判断是否是第一个文件,如果是则不需要添加"\r\n" if (idx != 0) { [mString appendString:@"\r\n"]; } [mString appendFormat:@"--%@\r\n", kBOUNDARY]; [mString appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", fieldName, [obj lastPathComponent]]; [mString appendString:@"Content-Type: application/octet-stream\r\n"]; [mString appendString:@"\r\n"]; [mData appendData:[mString dataUsingEncoding:NSUTF8StringEncoding]]; // 拼接文件的二进制数据 NSData *data = [NSData dataWithContentsOfFile:obj]; [mData appendData:data]; }]; // 构建数据 // ------WebKitFormBoundaryJa8BALfIc9saou2X // Content-Disposition: form-data; name="username" // // mazaiting // ------WebKitFormBoundaryJa8BALfIc9saou2X-- [params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { NSMutableString *mString = [NSMutableString string]; [mString appendFormat:@"\r\n--%@\r\n", kBOUNDARY]; [mString appendFormat:@"Content-Disposition: form-data; name=%@\r\n", key]; [mString appendString:@"\r\n"]; [mString appendFormat:@"%@", obj]; [mData appendData:[mString dataUsingEncoding:NSUTF8StringEncoding]]; }]; // 结束语句 NSString *end = [NSString stringWithFormat:@"\r\n--%@--", kBOUNDARY]; [mData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]]; return mData.copy; }

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册