本文旨在总结iOS知识网络,知识点,该知识网络罗列出常见UIKit、Foundation的对象特点和一些使用经验,可以看成是一本书;文本编辑采用树的形式,对知识点进行罗列,并标注一些使用经验(★)希望对初学者有用或给一些解决疑难杂症者提供思路;某些知识点会深入探讨;通过总结希望站在一个较高平台的角度全观Objective-C。知识树中有些是原创文章,有些则是转载网络上iOS大神的文章。由于篇幅的限制笔者会简洁地介绍各个知识点,读者可通过链接了解详情。当然一个人的知识面是相当有限的,在给各位读者提供知识参考的同时,欢迎大家对本文提意见。
/->UIViewController
| ViewController在iOS只是一个非常重要的概念【翻译】,其在一个App中所扮演的角色:
| (1) View Management:管理View (2) Data Marshalling:管理数据
| (3) User Interactions:响应用户交互 (4) Resource Management:管理资源
| (5) Adaptivity:适配不同的屏幕尺寸空间的变化
| ★ 生命周期【一片枫叶点击 另外一篇点击】
| + (void)initialize +(void)load 的调用时机,区别【点击】
| ViewDidLoad调用时机:当view被首次使用的时候,某些情况可提升性能
| 横竖屏的坑【点击】。APP整体是竖屏,单个controller可以是横屏的
| ★ 两种交互方式:push和present
| 左右滑动 - (void)pushViewController:(UIViewController *) animated:(BOOL)
| 模态,从下往上弹出 - (void)presentViewController:(UIViewController *) animated: (BOOL) completion:
| Can't add self as subview 这个crash是由于快速push两个UIViewController导致的【点击】
| ★ 一次dissmiss多个 present controller
| UIViewController *rootVC = self.presentingViewController;
| while (rootVC.presentingViewController)
| rootVC = rootVC.presentingViewController;
| [rootVC dismissViewControllerAnimated:YES completion:nil];
| ★pop到rootcontroller [UINavigationController popToRootViewControllerAnimated:]
| ★还有一种:直接把Controller的view添加到另一个Controller上。
|-> UIView
| frame 和bound 的区别【点击】
| frame 是相对父试图坐标的值; bound是本身坐标系统的值
| layoutSubviews【点击】 需要将[super layoutSubviews];放到最后,不然iOS7有可能会有这个崩溃
| ★ "Auto Layout still required after executing -layoutSubviews” iOS7上崩溃sdk缺陷 【点击】
| layoutSubviews在以下情况下会被调用:
| 1、init初始化不会触发layoutSubviews。
| 2、addSubview会触发layoutSubviews。
| 3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
| 4、滚动一个UIScrollView会触发layoutSubviews。
| 5、旋转Screen会触发父UIView上的layoutSubviews事件。
| 6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
| 7、直接调用setLayoutSubviews。
| 每一个视图有唯一的父视图【点击】。addsubview操作把它从上一个父试图中移除
| 善于使用hidden 使用animateWithDuration简单地控制页面切换效果
| 使用animateWithDuration简单地控制页面切换效果【点击】
| ★简单动画 animateWithDuration【点击】
| ★因为UIView没有实现copy协议,因此找不到copyWithZone方法,使用copy的时候导致崩溃,但是我们可以通过归档再解档实现copy,这相当于对视图进行了一次深拷贝
| UIView事件击穿,扩大按钮响应区域,通过重写hittest方法实现。【点击】
|->CALayer
| CALayer是个简单的类,它是用来在屏幕上显示内容展示的矩形区域.【容芳志出品点击】
| 直接从NSObject继承,少了UIResponder类,固CALayer悲催的不能响应任何用户事件【点击】
|-> UIWindow
| 每一个IOS程序都有一个UIWindow【译文】
| UIWindow有三个层级,分别是Normal,StatusBar,Alert【点击】
| keyWindow是指定的用来接收键盘以及非触摸类的消息,
| 而且程序中每一个时刻只能有一个window是keyWindow。
|-> UIImage
| 加载图片几种方式【点击】
| [UIImage imageNamed:@“xxx”] 系统缓存到cache中
| [UIImage imageWithContentsOfFile:path] 不缓存
| [UIImage imageWithData:data] 不缓存
| ★ 拉伸图片,四角保持不变 resizableImageWithCapInsets:
| ★ 加载gif图片【点击】
|-> UILabel【点击】
| 没有居上居下对齐,可以使用TTTAttributedLabel
| ★ 重写drawTextInRect:方法,可以自定义绘制区域,比如可设置Inset
| [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.textInsets)];
| ★ 设置行间距,通过设置label的attributedText来实现
/
/-> UIKit
| \
| |-> UIButton
| | 设置颜色,文字一定要指定button状态
| | ★善于使用contentEdgeInsets,imageEdgeInsets titleEdgeInsets可以设置文本边距【点击】
| | 设置圆角可layer.cornerRadius
| | ★UIButton 设置 imageView frame是无法改变大小的,大小就是图片的大小【点击】
| | 设置button上的title左对齐。仅仅设置label是没用的,需要:
| | ★ btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
| | ★去掉系统的按下高亮置灰效果 [btn setAdjustsImageWhenHighlighted:NO];
| |-> UITextfield
| | 隐藏键盘,[textfield resignFirstResponder]
| | ★ 任意页面隐藏键盘【点击】
| |-> UIScrollerView
| | 上拉下拉原理【点击】
| | Apple不建议在UIScrollerView上添加UITableview Important: You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
| |-> UITableView
| | 复用,注意重写 - (void)prepareForReuse
| | ★ 在-(void)layoutSubviews中设置subview的frame。否则frame总是(320,44)
| | dequeueReusableCellWithIdentifier 从重用池中获取,可能是nil
| | dequeueReusableCellWithReuseIdentifier 同上,但是不会是nil
| | 插入,删除,移动section或item的顺序,需遵循下面两个步骤【点击】
| | 1. 更新dataSource的数据
| | 2. 调用相应的collection view方法删除或者插入section或item
| | ★非常严格的条件:,在更新collection view之前,先更新datasource,
| | 因为collection view总是假设你已经准备好打他source了 否则collection view收到错误的item,并造成crash
| | 右侧音序条【点击】
| | UITableView上拉、下拉原理【点击】
| | AsyncDisplayKit 流畅的解决方法【点击】
| | ★tableView 在更改dataSource后需要立即调用reloadData,否则只要UI有刷新必crash。
| | ★tableView 在调用reloadData后,短时间内不要更改dataSource,尤其是将dataSource清空,否则只要ui有刷新必crash
| | ★tableView正在滚动的时候,如果reloadData,偶尔发生App crash的情况【点击】
| | ★UITableview Deceleration 加速滑动(惯性滑动)、弹性回归原理【点击】
| | ★UITableview 刷新某一个cell 或 section【点击】
| | ★UITableview 上拉隐藏搜索框,下拉出现搜索框【点击】
| | ★UITableview 是在willDisplayCell: 还是在cellForRowAtIndexPath: update data 呢?【点击】
| | ★UITableview UITableViewStylePlain模式,header不浮动【点击】
| | ★UITableview 当tableview的section比较多时候,内容也比较复杂,比如设计多个http接口。在更新tableview的时候一定要注意清除旧数据
| |-> UITableViewCell
| | ★UITableViewCell changes the background color of all sub views when cell is selected or highlighted.意思就是说当UITableViewCell被选中或者高亮的时候,它的所有子view的颜色都会改变。
| | 所以建议一般设置cell.selectionStyle = UITableViewCellSelectionStyleNone;
| |-> UIDevice
| | 设备名 [UIDevice currentDevice].name,
| | 系统版本号 [[UIDevice currentDevice].systemVersion doubleValue]; 【点击】
| | 屏幕旋转方向 [[UIDevice currentDevice] orientation]
| | 区分iPad还是iPhone [UIDevice currentDevice].userInterfaceIdiom);
| |-> UIScreen
| | 如何正确的绘制1像素的线【点击】
| | 保证边距不变,内容等比例拉伸【点击】
| |-> UIEdgeInsets
| | 实际显示边距,跟设置边距的距离【点击】
| \->自动布局
| Masonry 高级一点用法【多个label,可变长情况下使用Masonry】【点击】
| storyboard
| 在autolayout之前还有一种技术叫autoresizingmask,功能少一些。兄弟视图之间约束比较费劲
|
| /-> NSObject 既是对象也是协议,可以将对象自动置nil 比如 int = 0 bool = NO
| | 几乎所有类的基类或者协议【点击】
| | 类对象:程序中第一次使用该类的时候被创建,在整个程序中只有一份(类的实例则有多份)此后每次使用都是这个类对象,它在程序运行时一直存在【点击】。
| | isKindOfClass:和isMemberOfClass:,通过这两种方法可以确定一个类的从属关系\
| | 后者测试一个接收器是否是一个指定类的实例;而后者可以测试类的从属关系。
| | respondsToSelector: 方法测试一个接收器是否通过selector实现(implements)了一个标志符话的方法
| | description方法,允许一个对象返回一个字符串来描述它的内容;这个常用于调试debug
| | encodeWithCoder: 和 initWithCoder:方法,NSCoding协议中仅有的组成成员\
| | 第一个允许对象编译它的实例变量,第二个允许一个对象初始化它自身的解码实例变量。
| | conformsToProtocol:方法,测试接收器(对象或者类)符合一个给定的协议(protocol)
| | ★类对象中的 isa 指向类结构被称作 metaclass【点击】跟[object class]有点区别,比如KVO的时候
| | ★__weak如何实现对象值自动设置为nil的【点击】
| | ★如何判断两个对象相等,需要重写isEqual:方法和hash方法。虽然hash是为了对象加入set或者你是NSArray时候用的。但是判断两个对象是否相等,可以先hash,如果hash都不一样那么肯定不一样,接下来才是isEqual:方法的比较【点击】。使用hash只是提高判断效率。
| | 任何 Objective-C 都有 hash 方法,该方法返回一个 NSUInteger,是该对象的 hashCode【单击】
| | 任[self class]和 [super class]问题:self 是类的隐藏的参数,指向当前当前调用方法的类;super并不是隐藏的参数,它只是一个“编译器指示符”,它和self指向的是相同的消息接收者。所以两者都指向本类。【点击】
| |-> NSString & NSMutableString
| | NSString作为属性时候,用copy还是strong修饰?如果只是NSString没什么copy和strong区别。
| | 当NSString对象指向NSMutableString的时候,strong是单纯的增加对象的引用计数,而copy操作是执行了一次深拷贝【点击】
| |-> NSArray & NSMutableArray
| | NSArray 各种遍历方式,倒序遍历【点击】
| | NSArray简便初始化方法@[@"1",@"2"];
| | 浅拷贝。数组本身使用地址,但是数组item仍是旧对象【Apple 官方解释点击】
| | 无论copy、arrayWithArray、copyWithZone 数组内对象并没有变。
| | 只是copy出来的array是新地址,arrayWithArray出来的数组也是新地址。
| | 深拷贝。数组本身使用地址,但是数组item是新地址
| | [[NSArray alloc] initWithArray:someArray copyItems: YES];
| | 深拷贝时候,数组中的item必须实现NSCopying协议并实现copyWithZone:
| | ★防止NSArray was mutated while being enumerated
| | array包含array的情况深拷贝。NSArray* trueDeepCopyArray = [NSKeyedUnarchiver \
| | unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];
| | ★containsObject 注意:在对比数组中元素的时候,调用元素的isEqual的返回值。
| |-> NSDictionary & NSMutableDictionary
| | 取值时候,最好判断object的类型。 if ([object isKindOfClass:[NSString class]]){ //todo};
| |-> NSNumber 和 NSInteger NSRange
| | 前者专门用来装基础类型的对象,把整型、单精度、双精度、字符型等基础类型存储为对象
| |-> NSNull FMDB数据库,使用的时候崩溃
| | JsonKit转换以后会生出相应的[NSNull null]对象【点击】
| |-> NSData 字节缓冲区
| | + (nullable instancetype)dataWithContentsOfURL:(NSURL *)url
| | dataWithContentsOfURL 虽然是同步的,但可以结合gcd 异步加载网络图片【点击】
| |-> NSUserDefaults【点击】
| | 可用于APP setting 默认值不好用,SDK bug
| | 设置WebVIew的UA【点击】
| |-> NSDate & NSDateFormatter & NSCalendar
| | 可判断过去几个小时,还是几天 - (NSDateComponents *) components:fromDate:toDate:options:
| | 可获取时间戳
| | 有时候有8小时的时差,解决办法【点击】
| | 在开发iOS程序时对日期处理的总结【点击】
| | 当新的一天来到,或者说当运营商时间更新的时候,UIApplication会下发一个通知:UIApplication-SignificantTimeChangeNotification
| | 当系统的区域格式,或者时间格式(是否24小时制)改变时,下发通知:NSCurrentLocale-DidChangeNotification
| |-> NSCoding & NSCoder 仅有的两个方法,数据的序列号和反序列化【点击】
| | - (void)encodeWithCoder:(NSCoder *)aCoder;
| | - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
| |-> NSCopying & NSZone
| | + (instancetype)allocWithZone:深拷贝,类似于memcpy这样的C方法【点击】
| |-> NSAutoreleasePool
| | 降低内存峰值【点击】
| | 在Runloop休眠前(kCFRunLoopBeforeWaiting)时候释放自动释放池中的对象
| |-> NSFileManager 删除文件的时候先判断是否存在是个好习惯
| |-> NSTimer
| | NSTimer 简单使用 【点击】
| | ★ NSTimer定时器时间并不精确,类似于公交车进站,堵车就不准时【点击】
| |-> NSLog暴力打印,常用于测试【点击】
| |-> NSClassFromString 从字符串获取类。NSStringFromClass,从类名获取字符串
| | ★ 不要小瞧这两个API,配合使用,他可以做到代码逻辑解藕的效果。
| /
|-> Foundation
| \
| |-> NSIndexPath 链式结构;tableview用的比较多【点击】
| | 初始化 [NSIndexPath indexPathForRow:0 inSection:1];
| |-> NSError 网络变成经常用到
| |-> NSException
| |-> NSStringEncoding NSString的编码格式,了解即可【点击】
| |-> NSProgressIndicator
| |-> NSBundle 是个目录,包含了程序使用的资源,如图像,声音,编译好的代码,nib文件【点击】
| |-> NSNetServiceBrowser
| |-> NSValue 可以包装任意一个对象,可以用NSValue将struct存到NSArray和NSDictionary中。【点击】
| |-> NSURLConnection iOS9已不再使用
| |-> NSURLSession & NSURLSessionTask 【点击】NSURLSession提供的功能:
| | 通过URL将数据下载到内存【点击】
| | 通过URL将数据下载到文件系统
| | 将数据上传到指定URL
| | 在后台完成上述功能【点击】
| |-> NSURLRequest 包装了网络请求的信息【点击】
| |-> NSInputStream & NSOutputStream socket编程【点击】
| |-> NSPredicate
| | 谓语查询,原理和用法都类似于SQL中的where【点击】
| |-> NSLayoutConstraint 现在都用masonry
| |-> NSLock & NSRecursiveLock & NSCondition 多线程锁
| | 最基本的同步锁【点击】
| | @synchronized{//todo} 同样也是同步锁【点击】
| | 事实上信号量也能实现锁的目的,信号量和锁的区别【点击】第二篇【点击】
| |-> NSMethodSignature
/ | 配合NSInvocation实现消息转发【点击】
iOS |-> NSInvocation 直接调用 某个对象的消息【点击】
\ | iOS中可以直接调用 某个对象的消息 方式有2种performSelector:withObject: 和NSInvocation
| | 当然,还以用C语言的函数指针,参见下面的“方法调配技术”
| |-> NSSet 无序的对象集合,用处少
| |-> NSUrl 基本使用,包含File URL和File path【点击】
| |-> AVPlayer基本使用【点击】
| | 获取视频时间长度 【点击】
| \-> NSNotificationCenter 同步的机制【点击】注意防止重复,相似的机制还有delegate,observer,block
|
| /-> 创建push原理介绍、证书制作、测试push 专辑 【点击】
| | "iOS push全方位解析(一)【译文】"——iOS PUSH概述【点击】
| | "iOS push全方位解析(二)【译文】"——生成OpenSSL证书,Provisioning Profile【点击】
| | "iOS push全方位解析(三)【译文】"——一个极简的demo,并测试一下push【点击】
| /
|-> Push
| \
| | ★ iOS6、7、8、9 Push的演化 【点击】,但目前还是不尽人意(APP 无法获取通知栏消息数目)
| | ★ php写的可以在本机发送iOS push程序【点击】
| | iOS7 Background Remote Notification(后台远程通知——静默push)【点击】
| \-> 有一些三方push SDK:极光push
|
|-> block 必须掌握
| block专辑【点击】;Block带有局部变量的匿名函数;iOS开发尤其实用
| 【block编程第一篇】 block编程热点介绍(官方文档翻译的)【点击】
| 【block编程第二篇】 block捕获变量和对象【点击】
| 【block编程第三篇】block内存管理——如何验证block在栈上,还是堆上【点击】
| 【block编程第四篇】block的实现【点击】
| 【block编程第五篇】block中使用 weak–strong dance 技术避免循环引用【点击】
|-> 多线程
| iOS有三种多线程编程的技术,分别是:【点击】
| 1、NSThread 下面会讲到
| 2、Cocoa NSOperation 下面会讲到
| 3、GCD 下面会讲到
| 这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单。
| dispatch_once 执行一次,用于创建单例【点击】可满足线程安全
| iOS 不像C++ 那样,可以直接将构造函数设成private。所以创建绝对单例模型需重写allocWithZone,【点击】
|
| /-> 引用计数(retainCount)
| | retain 引用计数+1 对象alloc时,引用计数为1, release引用计数-1.引用计数=0时候,真正释放
| | autoRelease,自动释放对象【点击】
| |-> 便捷构造方法 iOS
| | 对象在自动释放池中,不需要开发者手动释放,比如下面的方法
| | NSString的stringWithString
| | NSArray的arrayWithObjects:和arrayWithArray:
| | UIImage的imageNamed:
| |-> 内存管理高级指南【官方译点击】
| |-> 内存管理实践【点击】
| /
|-> 内存管理【专栏点击】
| \
| |-> MRC 手动引用计数。release和retain成对儿
| \->ARC 自动引用计数
| ★强烈建议使用ARC
| ★禁止在函数内返回局部变量指针,不然就是野指针!
| ★容易引起循环引用的地方【点击】
| ★- (id)performSelector:(SEL)aSelector withObject:(id)object;引起警告
| warning:performSelector may cause a leak because its selector 【点击】
|
|-> 进程间通信(APP间通信)【点击】【点击】
| iOS可通过URL Scheme,调用别的APP(iOS内的应用调用协议),APP 实现 - (BOOL)application: openURL: options:
|
| /-> Runtime 运行时特点【《运行时之一:类与对象》南峰子出品 点击】
| | Objective-C程序员可以在程序运行时创建,检 查,修改类,对象和它们的方法【点击】
| | Objective-C runtime库也负责找出方法的最终执行代码
| | ★class Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。
| | struct objc_class {
| | Class isa OBJC_ISA_AVAILABILITY;
| | #if !__OBJC2__
| | Class super_class OBJC2_UNAVAILABLE; // 父类
| | const char *name OBJC2_UNAVAILABLE; // 类名
| | long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
| | long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
| | long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
| | struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
| | struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
| | struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存
| | struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
| | #endif
| | } OBJC2_UNAVAILABLE;
| | 1. isa:所有的类自身也是一个对象,这个对象的Class里面也有一个isa指针,它指向metaClass
| | 2. super_class:指向该类的父类,如果该类已经是最顶层的根类,则super_class为NULL。
| | 3. cache:用于缓存最近使用的方法。提高方法查找效率
| | ★objc_object与id objc_object是表示一个类的实例的结构体
| | struct objc_object {
| | Class isa OBJC_ISA_AVAILABILITY;
| | };
| | typedef struct objc_object *id;
| | 当创建一个类的实例对象时,分配的内存包含objc_object数据结构,然后是类的实例变量的数据。
| | NSObject类的alloc和allocWithZone:方法使用函数class_createInstance来创建objc_object数据结构。
| | 另外还有我们常见的id,它是一个objc_object结构类型的指针。id 其实就是一个 struct objc_object 类型的指针。但是 id 不是 NSObject * ,为什么可以指向任意的 NSObject 对象呢?因为 objc_object 只有一个 Class 类型的 isa 变量,而这个结构,恰恰和 NSObject 的定义一致
| | ★meta class元类,是一个类对象的类;它存储着一个类的所有类方法。
| | 当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;
| | 而向一个类发送消息时,会在这个类的meta-class的方法列表中查找。
| | ★继承体系【点击】
| | 动态创建类【点击】
| | objc_setAssociatedObject【点击】给对象增加属性,一般配合类别使用
| | object_getClass 得到一个实例的类【点击】
| | objc_copyImageNames 获取指定类所在动态库【南峰子出品点击】
| | objc_copyClassList 创建并返回一个指向所有已注册类的指针列表【点击】
| | class_xxx系列函数【点击】
| | class_copyPropertyList 获取类的属性
| | class_addMethod 为类添加方法
| | class_isMetaClass 判断是否为元类
| | class_getName 获取类名
| | class_copyIvarList 拷贝类的实例变量列表,注:这里特别要指出的是实例变量列表中的实例变量的定义如下,它包含了变量的名称、类型、偏移等,但却不包括变量的值-----值在对象而非类中
| | class_getInstanceMethod 获取实例方法
| |-> Runnloop 【ibireme出品 点击】
| | RunLoop 实际上就是一个对象,这个对象管理了其需要处理的事件和消息
| | 并提供了一个入口函数来执行上面 Event Loop 的逻辑
| | Run Loop并非iOS平台专属的概念,在任何平台的多线程编程中,为控制线程生命周期【点击】
| | 接收处理异步消息,都需要类似Run Loop的循环机制来实现:从简单的一个无限顺序
| | do{sleep(1);//执行消息}while(true),到高级平台,如Android的Looper,都是类似的机制。
| | 放在下一个runloop执行,保证当前执行正确【点击】
| | Runnloop基本作用 【点击】
| | ·保持程序的持续运行(比如主运行循环)
| | ·处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
| | ·节省CPU资源,提高程序性能:该做事时做事,该休息时休息
| | Runnloop应用
| | ·NSTimer 默认是NSDefaultRunLoopMode,滑动时候定时器不计时
| | ·ImageView显示 当用户在拖拽时(UI交互时)不显示图片,拖拽完成时显示图片
| | ·PerformSelector 设置运行模式
| | ·常驻线程 经常在后台进行耗时操作,如:监控联网状态,扫描沙盒等 不希望线程处理完事件就销毁,保持常驻状态
| | ·自动释放池 在休眠前(kCFRunLoopBeforeWaiting)进行释放,处理事件前创建释放池,中间创建的对象会放入释放池
| | ★PerformSelecter 当调用 NSObject 的 performSelecter:afterDelay: 后,实际上其内部会创建一个 Timer
| | 并添加到当前线程的 RunLoop 中;所以如果当前线程没有 RunLoop,则这个方法会失效【点击】
| /
|-> iOS 动态机制
| \
| |-> OC .(点)与->(箭头)用法区别。前者是访问setter和getter方法,后者是直接访问变量。
| |-> 消息传递 objc_msgSend【点击】【南峰子出品 点击】
| | obj-c脱胎于smalltalk的消息处理。所有方法调用都是发消息。消息是啥?一串字符【点击】
| | 如果向某对象传递消息,那就会使用动态绑定机制来决定需要调用的方法
| | objc_msgSend有两个隐藏参数,消息接收对象 方法的selector ,即(self,_cmd)
| |-> 消息转发 message forwarding【点击】
| | 就是对象在接收到无法解读的消息之后会发生什么情况
| | (1) +(BOOL) resolveInstanceMethod:(SEL)selector 类是否新增一个实例方法
| | (2) resolveClassMethod 是否新增了类方法
| | (3) -(id) forwardingTargetForSelector:(SEL)selector 能不能把这条消息转给其他接收者来注册
| | (4)-(void) forwardInvocation:(NSInvocation*)invocation 消息派发系统
| | (5)最后若都不能处理消息,则doesNotRecognizeSelector: 会抛出异常
| | ★当我们不能确定一个对象是否能接收某个消息时,会先调用respondsToSelector:来判断一下
| |-> SEL【点击】
| | SEL又叫选择器,是表示一个方法的selector的指针,每一个方法都对应着一个SEL。
| | OC在编译的时候,会根据方法的名字(包括参数序列),生成一个用 来区分这个方法的唯一的一个ID
| | 这个ID就是SEL类型的。需要注意的是,只要方法的名字(包括参数序列)相同,那么它们的ID都是相同的。
| | 就是 说,不管是超类还是子类,不管是有没有超类和子类的关系,只要名字相同那么ID就是一样的
| | ★方法的定义体里面,我们可以通过访问_cmd得到这个方法自己的SEL。
| |-> 方法调配技术 method swizzling 用于调试【南峰子出品点击】
| | IMP 它是objetive-C 方法(method)实现代码块的地址,实际上是函数指针,指向方法实现的首地址
| | IMP imp = [requestItem.delegateTarget methodForSelector:selector];
| | void (*func)(id, SEL, ResponseItem *) = (void *)imp;
| | func(requestItem.delegateTarget, selector, responseItem);
| | 可以从selector获取IMP,比如:- (IMP)methodForSelector:(SEL)aSelector;
| | Swizzling应该总是在+load中执行
| \-> 事件响应链【点击】另外一篇【点击】
| 在 iOS 中,几乎所有类都是 responder,比如 UIWindow、UIView、UIControl、UIControllers 等
| 当手指去触摸屏幕上 UIView 的实例对象 aView。产生一个触摸事件 UIEventTypeTouches
| 而接收触摸事件的对象 aView,就是一个 responder object。
| initial view –> super view –> …..–> view controller –> window –> Application –> AppDelegate
|
| /-> 沙盒(Sandbox)iOS沙盒机制【容芳志出品点击】
| | 每个应用程序都有自己的存储空间
| | 应用程序不能翻过自己的围墙去访问别的存储空间的内容
| | 应用程序请求的数据都要通过权限检测,假如不符合条件的话,不会被放行。
| |-> Group iOS8+数据共享,例如扩展(Extension)共享数据【点击】
| |-> Spotlight iOS9+ 系统搜索。【官方demo点击】
| |-> GCD(Grand Central Dispatch) iOS开发有一个强有力的多线程工具 【点击】
| | 多线程入门【raywenderlich出品 点击】
| | 系统提供一个叫做 主队列(main queue)
| | 系统还提供一个叫做全局调度队列(Global Dispatch Queues)有四个优先级
| | 开发者自己创建队列(串行,或者并行)
| | ★至少有五个队列任你处置:主队列、四个全局调度队列,再加上任何你自己创建的队列。
| | GCD 深入理解:第一部分【点击】
| | GCD 深入理解:第二部分【点击】
| | 开发常见方法介绍
| | dispatch_after 延后工作
| | Dispatch Groups 会在整个组的任务都完成时通知你
| | dispatch_semaphore_t 信号量,让你控制多个消费者对有限数量资源的访问。【点击】
| | dispatch_semaphore_wait 使得信号量-1,当=0时候阻塞
| | dispatch_semaphore_signal 释放信号量,即信号量+1
| | 信号量也可以实现两个异步操作,都完成时(即相互等待)。再执行一些操作。
| |
| |-> CoreData数据持久化,相比sqlite有下面优势【点击】
| | 数据库字段或者表有更改会导致crash,CoreData的版本管理和数据迁移变得非常有用,\
| | 手动写sql语句操作还是麻烦一些。
| | 不光能操纵SQLite,CoreData和iCloud的结合也很好,如果有这方面需求的话优先考虑
| | 并不是直接操纵数据库,比如:使用CoreData时不能设置数据库的主键,目前仍需要手动操作。
| | 效率上其实跑程序时感觉不出来,毕竟手机上的数据不能跟网站的数据和访问量相提并论。
| /
|-> 特殊封装&平台特性
| \
| |-> 类别(Category)扩展(Extension)的区别【点击】extension是在编译期的,它就是类的一部分;category是运行时期决议的,工作原理【点击】
| | 堪称iOS编程的精髓【点击】念茜出品【点击】
| |-> KVC 键值编码
| | 在IOS的中,没有绝对的私有,包括方法和变量,可以通过字符获取属性【点击】
| |-> KVO 键值观察,依赖isa-swizzling技术【王中周出品 点击】
| | 依赖Runtime 和KVC 一个新的类会动态被创建。详细原理【点击】另外一篇【点击】
| | 同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。
| | 然后系统将这个对象的 isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,
| | 因而在该对象上对 setter 的调用就会调用重写的 setter,从而激活键值通知机制
| | ★Person在建立KVO监听前和之后的打印输出 self->isa:Person [self class]:Person
| | self->isa:NSKVONotifying_Person [self class]:Person
| | ★比如:Tableview上拉下拉动画检测offset;播放视频,获取视频时长时候等
| | 为什么KVO不成对儿调用,会崩溃?
| |-> 多任务
| | 后台运行一段时间(不是地图,voip类app)【点击】
| |-> 3D Touch ,通过在plist中添加菜单,然后app实现下面的方法。进入APP
| | - (void)application: performActionForShortcutItem: completionHandler:
| |-> spotlight 通过系统搜索,进入APP【点击】
| \-> Touch ID 如何使用iOS 8 指纹识别,代码、实例【点击】
|-> HTTPs
| 建立安全链接
| 之前做过一段IM,对基本建立安全链接略知一二【点击】
| HTTPS进阶【点击】【本人总结】
| 一句话概括https的ssl加密过程:整个加密过程涉及:非对称加密和对称加密两种技术,其中非对称加密
| (由于RSA计算速度特别慢,无法对大量信息加密)用于简历安全链接,确保server和客户端
| 的合法(这需要证书机制);对称加密,则基于刚刚的安全链接之上,对传输内容的加密(加密速度很快)
| 整个过程需要4次握手
|
\-> iOS工具
转屏。APP本身是竖屏,但是某一个页面需要横屏【点击】
CrashHlytics Crash统计工具
AFNetworking 和 ASIHttp
SDImage
TMCache
AsyncDisplayKit 是 Facebook 推出的用于保持界面流畅性的框架
------------------------------------------------------------------------------------------
参考文献:《Objective-C高级编程:iOS与OS X多线程和内存管理》日本人写的;
《Effective Objective C 2.0:编写高质量iOS与OS X代码的52个有效方法》;
《Objective-C基础教程(第2版)》
网络博客参考(无循序):念茜、南峰子、ibireme、容芳志、唐巧、王巍、董柏然、阮一峰、一片枫叶,王中周,颐和园等博主
参考的公众帐号:《iOSDevTips》即唐巧的公众帐号;《iOSDevTip》
完整的UIKit和Foundation 结构 <点击>