2018-iOS开发学习与进阶

在iOS开发过程中,虽然我们能顺利地把项目写出来,甚至能够独立完成一个项目,但是有一些理论知识点我们会用就是很懵懂的了解,还是不能够深入理解其原理。本文是我在闲暇之际总结的一些简单的,常用的,但是还不够深入理解的小知识(精通者可以绕行了😂)!


1、iOS属性修饰符详解

常用的属性修饰符都有:assign,weak,copy,strong

assign:主要用于修饰基本数据类型(如NSInteger和CGFloat)和C数据类型(如int,float,double,char等),这些数值主要存在于栈上
weak:表示指向但不拥有该对象,其修饰的对象引用计数不会增加。无需手动设置,该对象会自行在内存中销毁。在ARC环境下,为避免循环引用,通常用来修饰delegate属性。
copy:建立一个索引计数为1的对象,然后释放旧对象。一般用于修饰有可变对应类型的不可变对象上,如NSString,NSArray,NSDictionary。也可以用来修饰block。
strong:表示指向并拥有该对象,其修饰的对象引用计数会增加1,相当于MRC下的retain。一般用于修饰自定义对象,UI控件对象,NSMutableString,NSMutableArray,NSMutableDictionary。

【copy与strong】
copy一般修饰NSString,NSArray,NSDictionary,block等。
strong一般修饰NSMutableString,NSMutableArray,NSMutableDictionary,还有自定义对象、UI控件对象等。
copy和strong 实际在的差异就在于setter的生成的方式不一样

1
2
3
4
//copy
- (void)setName:(NSString *)name {
_name = [name copy];
}

1
2
3
4
//strong
- (void)setName:(NSString *)name {
_name = name;
}

1、NSString为什么用copy而不用strong?
当源对象是NSString时,使用copy或strong没有区别。当源对象是NSMutableString时,strong属性只是增加了对象的引用计数,而copy属性是执行了一次深拷贝,所以strong属性的字符串会跟随源对象的改变而改变,copy属性的字符串不会随着源对象改变。一般我们定义了一个属性都不希望它能改变,所以一般都用copy关键字。
2、NSArray为什么用copy而不用strong?
正如NSString一样,当源对象是不可变的NSArray时,使用copy或strong没有区别。当源对象是NSMutableArray时,如果使用strong修饰,当NSMutableString改变时,NSArray这个不可变的数组也会改变。所以我们用copy修饰NSArray。
3、NSDictionary为什么用copy而不用strong?
同NSString和NSArray一样的道理。
4、NSMutableString为什么用strong而不用copy?
我们都知道不管是可变还是不可变类型的对象copy之后都返回不可变类型的对象,如果用copy修饰NSMutableString会返回一个不可变的NSString类型,当调用一些改变该字符串的方法(如[self.mString appendString:@”aa”])时,由于调用方法的对象是不可变类型会造成crash。所以一般可变类型对象用strong修饰,NSMutableArray,NSMutableDictionary同样的道理。

【strong与weak】
strong:强引用,相当于MRC下的retain,会使对象的引用计数+1,只要引用存在,对象就不会被销毁,当所有强引用消除时,对象才能被释放。
weak:弱引用,相当于MRC下的assign,不会使对象的引用计数+1,被weak修饰的对象随时可被系统销毁和回收。常用于修饰delegate。

2、iOS程序的生命周期

生命周期

3、UIViewController的生命周期

1
2
3
4
5
6
7
8
方法的调用顺序:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
- (void)loadView;
- (void)viewDidLoad;
- (void)viewWillAppear:(BOOL)animated;
- (void)viewDidAppear:(BOOL)animated;
- (void)viewWillDisappear:(BOOL)animated;
- (void)viewDidDisappear:(BOOL)animated;

4、Runtime

参考白开水写的一篇文章iOS模式详解—「runtime&runloop面试、工作」看我就🐒了^_^.,该文章介绍的非常详细!

【runtime概念】

  • Objective-C是基于C的,它为C添加了面向对象的特性。它将很多静态语言在编译和链接时期做的事放到了runtime运行时来处理,可以说runtime是我们Objective-C幕后工作者。
  • runtime是一套纯C(C和汇编)写的API。而OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。
  • 对于C语言,在编译的时候会决定调用哪个函数。
  • 对于OC,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用
  • 事实证明:在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错,只有当运行的时候才会报错,这是因为OC是运行时动态调用的。而C语言调用未实现的函数就会报错。

【runtime消息机制】

消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现。
每个类都有一个方法列表,存放着方法的名字和方法实现的映射关系,每个方法编号(selector)对应着一个函数指针(IMP),而函数指针就指向对应的方法实现。
在Objective-C中调用一个方法,其实是向一个对象发送消息,runtime就会根据对象的isa指针找到该对象对应的类或父类的方法列表,然后对象根据方法编号从方法列表中找到对应的函数指针(IMP),从而找到方法实现。

【runtime常见作用】

  • 动态交换两个方法的实现(method swizzling)
  • 动态添加属性
  • 实现字典转模型的自动转换
  • 发送消息
  • 动态添加方法
  • 拦截并替换方法
  • 实现 NSCoding 的自动归档和解档

5、分类与类扩展

首先要弄清楚什么是分类(类别),什么是类扩展

1
2
3
4
//分类(Category)
@interface NSObject (Category)
- (void)doSomething;
@end

1
2
3
4
//类扩展(Extension)
@interface NSObject ()
@property (nonatomic, copy) NSString *name;
@end

【分类(Category)】

  • 可以在不修改原类的基础上,为一个类扩展方法(主要用于给系统自带的类扩展方法),如果方法名与原类的方法名冲突了,则会优先执行分类的方法,因为分类具有更高的优先级。不可以删除原方法。
  • 分类只能添加方法,不能添加属性和成员变量。
  • 如果分类中声明了一个属性,那么分类只会生成这个属性的set和get方法的声明,不会实现。

【类扩展(Extension)】

  • 类扩展是分类的一个特例(有时被称为匿名分类),一般写在.m文件中
  • 可以为一个类添加私有的成员变量、属性、方法,并且添加的方法必须要实现。

【分类和类扩展的区别】

  • 类扩展能添加方法、成员变量和属性;分类只能添加方法,不能添加属性和成员变量(如果添加了属性,系统不会自动实现setter和getter方法,需要我们通过runtime实现)
  • 类扩展添加的方法必须要实现,分类可以不实现
  • 类扩展可以写在.m文件中,也可以写在.h文件中,写在.m中的是私有的,写在.h中的是公有的。

关于分类与类扩展介绍的比较详细的一篇文章

6、iOS远程推送的流程原理


1、应用程序注册苹果服务器的消息推送
2、iOS从苹果服务器获取到deviceToken,应用程序接收deviceToken
3、应用程序将接收到的deviceToken发送给程序的Push服务端
4、Push服务端向苹果服务器发送消息
5、苹果服务器将消息发送给iPhone手机的应用程序


坚持原创技术分享,您的支持将鼓励我继续创作!
0%