目录
1. 一、根底知识点
2. 二、第三方结构
3. 三、算法
4. 四、编码格式(优化细节)
5. 五、其他知识点
础知识点
设式是什么? 你知道哪些规划方法,并简要叙说?
规划方法是一种编码阅历,就是用比较老到的逻辑去处理某一种类型的作业。
1). MVC方法:Model View Control,把模型 视图 控制器 层进行解耦合编写。
2). MVVM方法:Model View ViewModel 把模型 视图 业务逻辑 层进行解耦和编写。
3). 单例方法:通过static关键词,声明全局变量。在整个进程作业期间只会被赋值一次。
4). 查询者方法:KVO是典型的查询者方法,查询某个特征的情况,情况发生改动时奉告查询者。
5). 托付方法:署理+协议的组合。结束1对1的反向传值操作。
6). 工厂方法:通过一个类方法,批量的根据已有模板出产方针。
MVC 和 MVVM 的差异
MVVM是对胖模型进行的拆分,其实质是给控制器减负,将一些弱业务逻辑放到VM中去处理。
MVC是全部规划的根底,全部新的规划方法都是根据MVC进行的改善。
参看:iOS MVVM架构总结
#import跟 #include 有什么差异,@class呢,#import<> 跟 #import””有什么差异?
1). #import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字,运用#import头文件会主动只导入一次,不会重复导入。
2). @class奉告编译器某个类的声明,当实施时,才去检查类的结束文件,可以处理头文件的彼此包含。
3). #import<>用来包含系统的头文件,#import””用来包含用户头文件。
frame 和 bounds 有什么不同?
frame指的是:该view在父view坐标系统中的方位和巨细。(参照点是父view的坐标系统)
bounds指的是:该view在本身坐标系统中的方位和巨细。(参照点是本身坐标系统)
Objective-C的类可以多重继承么?可以结束多个接口么?Category是什么?重写一个类的方法用继
承好仍是分类好?为什么?
答:Objective-C的类不行以多重继承;可以结束多个接口(协议);Category是类别;一般情况用分类好,用Category去重写类的方法,仅对本Category有用,不会影响到其他类与原有类的联络。
@property 的实质是什么?ivar、getter、setter 是怎样生成并添加到这个类中的
@property 的实质是什么?
@property = ivar + getter + setter;
“特征” (property)有两大约念:ivar(实例变量)、getter+setter(存取方法)
“特征” (property)作为 Objective-C 的一项特性,首要的作用就在于封装方针中的数据。 Objective-C 方针一般会把其所需求的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其间,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。
@property中有哪些特征关键字?/ @property 后边可以有哪些修饰符?
特征可以具有的特质分为四类:
1.原子性— nonatomic 特质
2.读/写权限—readwrite(读写)、readonly (只读)
3.内存处理语义—assign、strong、 weak、unsafe_unretained、copy
4.方法名—getter=、setter=
5.不常用的:nonnull,null_resettable,nullable
特征关键字 readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
1). readwrite 是可读可写特性。需求生成getter方法和setter方法。
2). readonly 是只读特性。只会生成getter方法,不会生成setter方法,不期望特征在类外改动。
3). assign 是赋值特性。setter方法将传入参数赋值给实例变量;仅设置变量时,assign用于底子数据类型。
4). retain(MRC)/strong(ARC) 标明持有特性。setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。
5). copy 标明拷贝特性。setter方法将传入方针拷贝一份,需求完全一份新的变量时。
6). nonatomic 非原子操作。不写的话默许就是atomic。atomic 和 nonatomic 的差异在于,系统主动生成的 getter/setter 方法不相同。关于atomic的特征,系统生成的 getter/setter 会保证 get、set 操作的无缺性,而nonatomic就没有这个保证了。所以,nonatomic的速度要比atomic快。
不过atomic可并不能保证线程安全。
参看:[爆栈抢手 iOS 问题] atomic 和 nonatomic 有什么差异?
什么情况运用 weak 关键字,比较 assign 有什么不同?
1.在 ARC 中,在有或许出现循环引用的时分,往往要通过让其间一端运用 weak 来处理,比如: delegate 署理特征。
2.本身现已对它进行一次强引用,没有必要再强引用一次,此时也会运用 weak,自定义 IBOutlet 控件特征一般也运用 weak;当然,也可以运用strong。
IBOutlet连出来的视图特征为什么可以被设置成weak?
因为父控件的subViews数组现已对它有一个强引用。
不同点:
assign 可以用非 OC 方针,而 weak 有必要用于 OC 方针。
weak 标明该特征定义了一种“非具有联络”。在特征所指的方针销毁时,特征值会主动清空(nil)。
怎样用 copy 关键字?
用处:
- NSString、NSArray、NSDictionary 等等常常运用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;
- block 也常常运用 copy 关键字。
阐明:
block 运用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,运用 copy 可以把它放到堆区.在 ARC 中写不写都行:关于 block 运用 copy 仍是 strong 作用是相同的,但写上 copy 也无伤大雅,还能时间提醒咱们:编译器主动对 block 进行了 copy 操作。假设不写 copy ,该类的调用者有或许会忘掉或许底子不知道“编译器会主动对 block 进行了 copy 操作”,他们有或许会在调用之前自行拷贝特征值。这种操作剩余而低效。
用@property声明的 NSString / NSArray / NSDictionary 常常运用 copy 关键字,为什么?假设改用strong关键字,或许构成什么问题?
答:用 @property 声明 NSString、NSArray、NSDictionary 常常运用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间或许进行赋值操作(就是把可变的赋值给不行变的),为保证方针中的字符串值不会无意间改动,应该在设置新特征值时拷贝一份。
- 因为父类指针可以指向子类方针,运用 copy 的目的是为了让本方针的特征不受外界影响,运用 copy 不论给我传入是一个可变方针仍是不行方针,我本身持有的就是一个不行变的副本。
- 假设咱们运用是 strong ,那么这个特征就有或许指向一个可变方针,假设这个可变方针在外部被批改了,那么会影响该特征。
总结:运用copy的目的是,避免把可变类型的方针赋值给不行变类型的方针时,可变类型方针的值发送改动会无意间篡改不行变类型方针本来的值。
浅拷贝和深拷贝的差异?
浅拷贝:只拷贝指向方针的指针,而不拷贝引用方针本身。
深拷贝:拷贝引用方针本身。内存中存在了两份独立方针本身,当批改A时,A_copy不变。
系统方针的 copy 与 mutableCopy 方法
不论是集结类方针(NSArray、NSDictionary、NSSet … 之类的方针),仍是非集结类方针(NSString, NSNumber … 之类的方针),接收到copy和mutableCopy消息时,都遵循以下原则:
- copy 回来的是不行变方针(immutableObject);假设用copy回来值调用mutable方针的方法就会crash。
- mutableCopy 回来的是可变方针(mutableObject)。
1. 一、非集结类方针的copy与mutableCopy
2. 在非集结类方针中,对不行变方针进行copy操作,是指针拷贝,mutableCopy操作是内容拷贝;
3. 对可变方针进行copy和mutableCopy都是内容拷贝。用代码简略标明如下: NSString *str = @"hello word!"; NSString *strCopy = [str copy] // 指针拷贝,strCopy与str的地址相同 NSMutableString *strMCopy = [str mutableCopy] // 内容拷贝,strMCopy与str的地址不相同 NSMutableString *mutableStr = [NSMutableString stringWithString: @"hello word!"]; NSString *strCopy = [mutableStr copy] // 内容拷贝 NSMutableString *strMCopy = [mutableStr mutableCopy] // 内容拷贝
1. 二、集结类方针的copy与mutableCopy (同上)
2. 在集结类方针中,对不行变方针进行copy操作,是指针拷贝,mutableCopy操作是内容拷贝;
3. 对可变方针进行copy和mutableCopy都是内容拷贝。但是:集结方针的内容拷贝仅限于方针本身,对集结内的方针元素仍然是指针拷贝。(即单层内容拷贝) NSArray *arr = @[@[@"a", @"b"], @[@"c", @"d"]; NSArray *copyArr = [arr copy]; // 指针拷贝 NSMutableArray *mCopyArr = [arr mutableCopy]; //单层内容拷贝 NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil]; NSArray *copyArr = [mutableArr copy]; // 单层内容拷贝 NSMutableArray *mCopyArr = [mutableArr mutableCopy]; // 单层内容拷贝
【总结一句话】:
只要对不行变方针进行copy操作是指针拷贝(浅拷贝),其它情况都是内容拷贝(深拷贝)!
这个写法会出什么问题:@property (nonatomic, copy) NSMutableArray *arr;
问题:添加,删去,批改数组内的元素的时分,程序会因为找不到对应的方法而溃散。
//如:-[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x7fcd1bc30460
// copy后回来的是不行变方针(即 arr 是 NSArray 类型,NSArray 类型方针不能调用 NSMutableArray 类型方针的方法)
原因:是因为 copy 就是拷贝一个不行变 NSArray 的方针,不能对 NSArray 方针进行添加/批改。
怎样让自己的类用 copy 修饰符?怎样重写带 copy 关键字的 setter?
若想令自己所写的方针具有拷贝功用,则需结束 NSCopying 协议。假设自定义的方针分为可变版别与不行变版别,那么就要一起结束 NSCopying 与 NSMutableCopying 协议。
具体过程:
- 需声明该类遵循 NSCopying 协议
- 结束 NSCopying 协议的方法。
// 该协议只要一个方法:
- (id)copyWithZone:(NSZone *)zone;
// 留心:运用 copy 修饰符,调用的是copy方法,其实实在需求结束的是 “copyWithZone” 方法。
写一个 setter 方法用于结束 @property (nonatomic, retain) NSString *name,写一个 setter 方法用于结束 @property (nonatomic, copy) NSString *name
1. // retain - (void)setName:(NSString *)str {
2. [str retain];
3. [_name release];
4. _name = str;
5. } // copy - (void)setName:(NSString *)str {
6. id t = [str copy];
7. [_name release];
8. _name = t;
9. }
@synthesize 和 @dynamic 别离有什么作用?
@property有两个对应的词,一个是@synthesize(合成实例变量),一个是@dynamic。
假设@synthesize和@dynamic都没有写,那么默许的就是 @synthesize var = _var;
// 在类的结束代码里通过 @synthesize 语法可以来指定实例变量的名字。(@synthesize var = _newVar;)
- @synthesize 的语义是假设你没有手动结束setter方法和getter方法,那么编译器会主动为你加上这两个方法。
- @dynamic 奉告编译器,特征的setter与getter方法由用户自己结束,不主动生成(如,@dynamic var)。
常见的 Objective-C 的数据类型有那些,和C的底子数据类型有什么差异?如:NSInteger和int
Objective-C的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,创建后就是方针,而C言语的底子数据类型int,仅仅必定字节的内存空间,用于存放数值;NSInteger是底子数据类型,并不是NSNumber的子类,当然也不是NSObject的子类。NSInteger是底子数据类型Int或许Long的别号(NSInteger的定义typedef long NSInteger),它的差异在于,NSInteger会根据系统是32位仍是64位来决议是本身是int仍是long。
id 声明的方针有什么特性?
id 声明的方针具有作业时的特性,即可以指向任意类型的Objcetive-C的方针。
Objective-C 怎样对内存处理的,说说你的看法和处理方法?
答:Objective-C的内存处理首要有三种方法ARC(主动内存计数)、手动内存计数、内存池。
1). 主动内存计数ARC:由Xcode主动在App编译阶段,在代码中添加内存处理代码。
2). 手动内存计数MRC:遵循内存谁申请、谁开释;谁添加,谁开释的原则。
3). 内存开释池Release Pool:把需求开释的内存共同放在一个池子中,当池子被抽干后(drain),池子中全部的内存空间也被主动开释掉。内存池的开释操作分为主动和手动。主动开释受runloop机制影响。
Objective-C 中创建线程的方法是什么?假设在主线程中实施代码,方法是什么?假设想延时实施代码、方法又是什么?
答:线程创建有三种方法:运用NSThread创建、运用GCD的dispatch、运用子类化的NSOperation,然后将其参与NSOperationQueue;在主线程实施代码,方法是performSelectorOnMainThread,假设想延时实施代码可以用performSelector:onThread:withObject:waitUntilDone:
Category(类别)、 Extension(扩展)和继承的差异
差异:
- 分类有名字,类扩展没有分类名字,是一种特别的分类。
- 分类只能扩展方法(特征仅仅是声明,并没实在结束),类扩展可以扩展特征、成员变量和方法。
- 继承可以添加,批改或许删去方法,并且可以添加特征。
咱们说的OC是动态作业时言语是什么意思?
答:首要是将数据类型的承认由编译时,推延到了作业时。简略来说, 作业时机制使咱们直到作业时才去决议一个方针的类别,以及调用该类别方针指定方法。
为什么咱们常见的delegate特征都用是week而不是retain/strong?
答:是为了避免delegate两端发生不用要的循环引用。
@property (nonatomic, weak) iddelegate;
什么时分用delete,什么时分用Notification?
Delegate(托付方法):1对1的反向消息奉告功用。
Notification(奉告方法):只想要把消息发送出去,奉告某些情况的改动。但是并不关心谁想要知道这个。
什么是 KVO 和 KVC?
1). KVC(Key-Value-Coding):键值编码 是一种通过字符串直接访问方针的方法(即给特征赋值)
举例阐明:
stu.name= @”张三” // 点语法给特征赋值
[stu setValue:@”张三” forKey:@”name”]; // 通过字符串运用KVC方法给特征赋值
stu1.nameLabel.text = @”张三”;
[stu1 setValue:@”张三” forKey:@”nameLabel.text”]; // 跨层赋值
2). KVO(key-Value-Observing):键值查询机制 他供应了查询某一特征改动的方法,极大的简化了代码。
KVO只能被KVC触发,包含运用setValue:forKey:方法和点语法。
// 通过下方方法为特征添加KVO查询
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
// 当被查询的特征发送改动时,会主动触发下方方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
KVC 和 KVO 的 keyPath 可以是特征、实例变量、成员变量。
iOS 成员变量,特征变量,局部变量,实例变量,全局变量 详解
KVC的底层结束?
当一个方针调用setValue方法时,方法内部会做以下操作:
1). 检查是否存在相应的key的set方法,假设存在,就调用set方法。
2). 假设set方法不存在,就会查找与key相同称谓并且带下划线的成员变量,假设有,则直接给成员变量特征赋值。
3). 假设没有找到_key,就会查找相同称谓的特征key,假设有就直接赋值。
4). 假设还没有找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。
这些方法的默许结束都是抛出异常,咱们可以根据需求重写它们。
ViewController生命周期
按照实施次序摆放:
- initWithCoder:通过nib文件初始化时触发。
- awakeFromNib:nib文件被加载的时分,会发生一个awakeFromNib的消息到nib文件中的每个方针。
- loadView:开端加载视图控制器自带的view。
- viewDidLoad:视图控制器的view被加载结束。
- viewWillAppear:视图控制器的view行将闪现在window上。
- updateViewConstraints:视图控制器的view开端更新AutoLayout捆绑。
- viewWillLayoutSubviews:视图控制器的view行将更新内容视图的方位。
- viewDidLayoutSubviews:视图控制器的view现已更新视图的方位。
- viewDidAppear:视图控制器的view现已展示到window上。
- viewWillDisappear:视图控制器的view行将从window上消失。
- viewDidDisappear:视图控制器的view现已从window上消失。
方法和选择器有何不同?
selector是一个方法的名字,方法是一个组合体,包含了名字和结束。
你是否触摸过OC中的反射机制?简略聊一下概念和运用
1). class反射
通过类名的字符串方法实例化方针。
Class class = NSClassFromString(@”student”);
Student *stu = [[class alloc] init];
将类名变为字符串。
Class class =[Student class];
NSStringclassName = NSStringFromClass(class);2). SEL的反射通过方法的字符串方法实例化方法。SEL selector = NSSelectorFromString(@”setName”);[stu performSelector:selector withObject:@”Mike”];将方法变成字符串。NSStringFromSelector(@selector(setName:));
调用方法有两种方法:
1). 直接通过方法名来调用。[person show];
2). 直接的通过SEL数据来调用 。SEL aaa = @selector(show); [person performSelector:aaa];
怎样对iOS设备进行功用测验?
答: Profile-> Instruments ->Time Profiler
开发项目时你是怎样检查内存泄露?
1). 静态分析 analyze。
2). instruments东西里面有个leak可以动态分析。
什么是懒加载?
答:懒加载就是只在用到的时分才去初始化。也可以了解成延时加载。
我觉得最好也最简略的一个比便当是tableView中图片的加载闪现了, 一个延时加载, 避免内存过高,一个异步加载,避免线程阻塞前进用户体会。
类变量的 @public,@protected,@private,@package 声明各有什么含义?
@public 任何当地都能访问;
@protected 该类和子类中访问,是默许的;
@private 只能在本类中访问;
@package 本包内运用,跨包不行以。
什么是谓词?
谓词就是通过NSPredicate给定的逻辑条件作为捆绑条件,结束对数据的选择。
//定义谓词方针,谓词方针中包含了过滤条件(过滤条件比较多)
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”age<%d”,30];
//运用谓词条件过滤数组中的元素,过滤之后回来查询的作用
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
isa指针问题
isa:是一个Class 类型的指针. 每个实例方针有个isa的指针,他指向方针的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调 用时,先会从本身查找类方法的结束,假设没有,元类会向他父类查找该方法。一起留心的是:元类(meteClass)也是类,它也是方针。元类也有isa指针,它的isa指针毕竟指向的是一个根元类(root meteClass)。根元类的isa指针指向本身,这样构成了一个关闭的内循环。
怎样访问并批改一个类的私有特征?
1). 一种是通过KVC获取。
2). 通过runtime访问并批改私有特征。
一个objc方针的isa的指针指向什么?有什么作用?
答:指向他的类方针,然后可以找到方针上的方法。
下面的代码输出什么?
@implementation Son : Father
- (id)init {
if (self = [super init]) {
NSLog(@”%@”, NSStringFromClass([self class])); // Son
NSLog(@”%@”, NSStringFromClass([super class])); // Son
}
return self;
}
@end
// 解析:
self 是类的躲藏参数,指向当时调用方法的这个类的实例。
super是一个Magic Keyword,它实质是一个编译器标明符,和self是指向的同一个消息接收者。
不同的是:super会奉告编译器,调用class这个方法时,要去父类的方法,而不是本类里的。
上面的比如不论调用[self class]仍是[super class],承受消息的方针都是当时 Son *obj 这个方针。
写一个无缺的署理,包含声明、结束
1. // 创建 @protocol MyDelagate @required -(void)eat:(NSString *)foodName;
2. @optional -(void)run;
3. @end // 声明 .h @interface person: NSObject
4.
5. @end // 结束 .m @implementation person - (void)eat:(NSString *)foodName { NSLog(@"吃:%@!", foodName);
6. }
7. - (void)run { NSLog(@"run!");
8. }
9.
10. @end
isKindOfClass、isMemberOfClass、selector作用别离是什么
isKindOfClass:作用是某个方针归于某个类型或许继承自某类型。
isMemberOfClass:某个方针确切归于某个类型。
selector:通过方法名,获取在内存中的函数的进口地址。
delegate 和 notification 的差异
1). 二者都用于传递消息,不同之处首要在于一个是1对1的,另一个是一对多的。
2). notification通过维护一个array,结束一对多消息的转发。
3). delegate需求两者之间有必要建立联络,否则无法调用署理的方法;notification不需求两者之间有联络。
什么是block?
闭包(block):闭包就是获取其它函数局部变量的匿名函数。
block反向传值
1. * 在控制器间传值可以运用署理或许block,运用block相对来说简练。
2.
3. * 在前一个控制器的touchesBegan:方法内结束如下代码。 // OneViewController.m TwoViewController *twoVC = [[TwoViewController alloc] init];
4. twoVC.valueBlcok = ^(NSString *str) { NSLog(@"OneViewController拿到值:%@", str);
5. };
6. [self presentViewController:twoVC animated:YES completion:nil]; // TwoViewController.h (在.h文件中声明一个block特征) @property (nonatomic ,strong) void(^valueBlcok)(NSString *str); // TwoViewController.m (在.m文件中结束方法) - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 传值:调用block if (_valueBlcok) {
7. _valueBlcok(@"123456");
8. }
9. }
block的留心点
1). 在block内部运用外部指针且会构成循环引用情况下,需求用__week修饰外部指针:
__weak typeof(self) weakSelf = self;
2). 在block内部假设调用了延时函数还运用弱指针会取不到该指针,因为现已被销毁了,需求在block内部再将弱指针从头强引用一下。
__strong typeof(self) strongSelf = weakSelf;
3). 假设需求在block内部改动外部栈区变量的话,需求在用__block修饰外部变量。
BAD_ACCESS在什么情况下出现?
答:这种问题在开发时常常遇到。原因是访问了野指针,比如访问现已开释方针的成员变量或许发消息、死循环等。
lldb(gdb)常用的控制台调试指令?
1). p 输出底子类型。是打印指令,需求指定类型。是print的简写
p (int)[[[self view] subviews] count]
2). po 打印方针,会调用方针description方法。是print-object的简写
po [self view]
3). expr 可以在调试时动态实施指定表达式,并将作用打印出来。常用于在调试进程中批改变量的值。
4). bt:打印调用库房,是thread backtrace的简写,加all可打印全部thread的库房
5). br l:是breakpoint list的简写
你一般是怎样用Instruments的?
Instruments里面东西许多,常用:
1). Time Profiler: 功用分析
2). Zombies:检查是否访问了僵尸方针,但是这个东西只能从上往下检查,不智能。
3). Allocations:用来检查内存,写算法的那批人也用这个来检查。
4). Leaks:检查内存,看是否有内存泄露。
iOS中常用的数据存储方法有哪些?
数据存储有四种计划:NSUserDefault、KeyChain、File、DB。
其间File有三种方法:writeToFile:atomically:、Plist、NSKeyedAchiever(归档)
DB包含:SQLite、FMDB、CoreData
iOS的沙盒目录结构是怎样的?
沙盒结构:
- AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。因为应用程序有必要通过签名,所以您在作业时不能对这个目录中的内容进行批改,否则或许会使应用程序无法发起。
- Documents:您应该将全部的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据。iCloud备份目录。(这儿不能存缓存文件,否则上架不被通过)
- Library 目录:这个目录下有两个子目录:
Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该运用NSUserDefaults类来取得和设置应用程序的偏好.
Caches 目录:用于存放应用程序专用的支撑文件,保存应用程序再次发起进程中需求的信息。
可创建子文件夹。可以用来放置您期望被备份但不期望被用户看到的数据。该途径下的文件夹,除Caches以外,都会被iTunes备份。 - tmp:存放临时文件,不会被备份,并且这个文件下的数据有或许随时被铲除的或许。
iOS多线程技术有哪几种方法?
答:pthread、NSThread、GCD、NSOperation
GCD 与 NSOperation 的差异:
GCD 和 NSOperation 都是用于结束多线程:
GCD 根据C言语的底层API,GCD首要与block结合运用,代码简练高效。
NSOperation 归于Objective-C类,是根据GCD更高一层的封装。凌乱任务一般用NSOperation结束。
写出运用GCD方法从子线程回到主线程的方法代码
答:dispatch_sync(dispatch_get_main_queue(), ^{ });
怎样用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载结束后合成一张整图)
// 运用Dispatch Group追加block到Global Group Queue,这些block假设全部实施结束,就会实施Main Dispatch Queue中的结束处理的block。
// 创建队伍组
dispatch_group_t group = dispatch_group_create();
// 获取全局并发队伍
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{ /*加载图片1/ });dispatch_group_async(group, queue, ^{ /加载图片2/ });dispatch_group_async(group, queue, ^{ /加载图片3 */ });
// 当并发队伍组中的任务实施结束后才会实施这儿的代码
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 兼并图片
});
dispatch_barrier_async(栅栏函数)的作用是什么?
1. 函数定义:dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
2. 作用: 1.在它前面的任务实施结束后它才实施,它后边的任务要等它实施结束后才会开端实施。 2.避免数据比赛 // 1.创建并发队伍 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT); // 2.向队伍中添加任务 dispatch_async(queue, ^{ // 1.2是并行的 NSLog(@"任务1, %@",[NSThread currentThread]);
3. }); dispatch_async(queue, ^{ NSLog(@"任务2, %@",[NSThread currentThread]);
4. });
5.
6. dispatch_barrier_async(queue, ^{ NSLog(@"任务 barrier, %@", [NSThread currentThread]);
7. }); dispatch_async(queue, ^{ // 这两个是一起实施的 NSLog(@"任务3, %@",[NSThread currentThread]);
8. }); dispatch_async(queue, ^{ NSLog(@"任务4, %@",[NSThread currentThread]);
9. }); // 输出作用: 任务1 任务2 ——》 任务 barrier ——》任务3 任务4 // 其间的任务1与任务2,任务3与任务4 由所以并行处理先后次序不定。
以下代码作业作用怎样?
1. - (void)viewDidLoad {
2. [super viewDidLoad]; NSLog(@"1"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"2");
3. }); NSLog(@"3");
4. } // 只输出:1。(主线程死锁)
什么是 RunLoop
- 从字面上看,就是作业循环,跑圈
- 其实它内部就是do-while循环,在这个循环内部不断地处理各种任务(比如Source、Timer、Observer)
- 一个线程对应一个RunLoop,底子作用就是保持程序的继续作业,处理app中的各种作业。
- 通过runloop,有事作业,没事就休息,可以节省cpu资源,前进程序功用。
主线程的run loop默许是发起的。iOS的应用程序里面,程序发起后会有一个如下的main()函数
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
RunLoop学习总结
说说你对 runtime 的了解
Runtime又叫作业时,是一套底层的C言语API,其为iOS内部的核心之一,咱们平常编写的OC代码,底层都是根据它来结束的。
Runtime结束的机制是什么,怎样用,一般用于干嘛?
1). 运用时需求导入的头文件
2). Runtime 作业时机制,它是一套C言语库。
3). 实际上咱们编写的全部OC代码,毕竟都是转成了runtime库的东西。
比如:
类转成了 Runtime 库里面的结构体等数据类型,
方法转成了 Runtime 库里面的C言语函数,
平常调方法都是转成了 objc_msgSend 函数(所以说OC有个消息发送机制)
// OC是动态言语,每个方法在作业时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。
// [stu show]; 在objc动态编译时,会被转意为:objc_msgSend(stu, @selector(show));
4). 因此,可以说 Runtime 是OC的底层结束,是OC的暗地实施者。
有了Runtime库,能做什么作业呢?
Runtime库里面包含了跟类、成员变量、方法相关的API。
比如:
(1)获取类里面的全部成员变量。
(2)为类动态添加成员变量。
(3)为类动态添加新的方法。
(4)动态改动类的方法结束等。(Method Swizzling)
因此,有了Runtime,想怎样改就怎样改。
什么是 Method Swizzle(黑魔法),什么情况下会运用?
1). 在没有一个类的结束源码的情况下,想改动其间一个方法的结束,除了继承它重写、和凭借类别重名方法暴力抢先之外,还有愈加活络的方法 Method Swizzle。
2). Method Swizzle 指的是改动一个已存在的选择器对应的结束的进程。OC中方法的调用可以在作业时通过改动,通过改动类的调度表中选择器到毕竟函数间的映射联络。
3). 在OC中调用一个方法,其实是向一个方针发送消息,查找消息的仅有根据是selector的名字。运用OC的动态特性,可以结束在作业时掉包selector对应的方法结束。
4). 每个类都有一个方法列表,存放着selector的名字和方法结束的映射联络。IMP有点类似函数指针,指向具体的方法结束。
5). 咱们可以运用 method_exchangeImplementations 来沟通2个方法中的IMP。
6). 咱们可以运用 class_replaceMethod 来批改类。
7). 咱们可以运用 method_setImplementation 来直接设置某个方法的IMP。
8). 归根到底,都是掉包了selector的IMP。
_objc_msgForward 函数是做什么的,直接调用它将会发生什么?
答:_objc_msgForward是 IMP 类型,用于消息转发的:当向一个方针发送一条消息,但它并没有结束的时分,_objc_msgForward会尝试做消息转发。
什么是 TCP / UDP ?
TCP:传输控制协议。
UDP:用户数据协议。
TCP 是面向衔接的,建立衔接需求阅历三次握手,是可靠的传输层协议。
UDP 是面向无衔接的,数据传输是不可靠的,它只管发,不论收不收得到。
简略的说,TCP注重数据安全,而UDP数据传输快点,但安全性一般。
通信底层原理(OSI七层模型)
OSI采用了分层的结构化技术,共分七层:
物理层、数据链路层、网络层、传输层、会话层、标明层、应用层。
介绍一下XMPP?
XMPP是一种以XML为根底的开放式实时通信协议。
简略的说,XMPP就是一种协议,一种规则。就是说,在网络上传东西,XMM就是规则你上传巨细的格式。
OC中创建线程的方法是什么?假设在主线程中实施代码,方法是什么?
1. // 创建线程的方法 - [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]
2. - [self performSelectorInBackground:nil withObject:nil];
3. - [[NSThread alloc] initWithTarget:nil selector:nil object:nil];
4. - dispatch_async(dispatch_get_global_queue(0, 0), ^{});
5. - [[NSOperationQueue new] addOperation:nil]; // 主线程中实施代码的方法 - [self performSelectorOnMainThread:nil withObject:nil waitUntilDone:YES];
6. - dispatch_async(dispatch_get_main_queue(), ^{});
7. - [[NSOperationQueue mainQueue] addOperation:nil];
tableView的重用机制?
答:UITableView 通过重用单元格来到达节省内存的目的: 通过为每个单元格指定一个重用标识符,即指定了单元格的种类,当屏幕上的单元格滑出屏幕时,系统会把这个单元格添加到重用队伍中,等候被重用,当有新单元格从屏幕外滑入屏幕内时,从重用队伍中找看有没有可以重用的单元格,假设有,就拿过来用,假设没有就创建一个来运用。
用伪代码写一个线程安全的单例方法
1. static id _instance;
2. + (id)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
3. _instance = [super allocWithZone:zone];
4. }); return _instance;
5. }
6.
7. + (instancetype)sharedData { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
8. _instance = [[self alloc] init];
9. }); return _instance;
10. }
11.
12. - (id)copyWithZone:(NSZone *)zone { return _instance;
13. }
怎样结束视图的变形?
答:通过批改view的 transform 特征即可。
在手势方针根底类UIGestureRecognizer的常用子类手势类型中哪两个手势发生后,呼应只会实施一次?
答:UITapGestureRecognizer,UISwipeGestureRecognizer是一次性手势,手势发生后,呼应只会实施一次。
字符串常用方法:
NSStringstr = @”abc123″;
NSArrayarr = [str componentsSeparatedByString:@””]; //以方针字符串把原字符串分割成两部分,存到数组中。@[@”abc”, @”123″];
怎样高功用的给 UIImageView 加个圆角?
1. * 欠好的处理计划:运用下面的方法会`强制Core Animation提前渲染屏幕的离屏制造, 而离屏制造就会给功用带来负面影响`,会有卡顿的现象出现。 self.view.layer.cornerRadius = 5.0f; self.view.layer.masksToBounds = YES;
2.
3. * 正确的处理计划:运用绘图技术
4.
5. - (UIImage *)circleImage { // NO代表通明 UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 取得上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 添加一个圆 CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); CGContextAddEllipseInRect(ctx, rect); // 裁剪 CGContextClip(ctx); // 将图片画上去 [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 关闭上下文 UIGraphicsEndImageContext(); return image;
6. }
7.
8. * 还有一种计划:运用了贝塞尔曲线"切开"个这个图片, 给UIImageView 添加了的圆角,其实也是通过绘图技术来结束的。 UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
9. imageView.center = CGPointMake(200, 300); UIImage *anotherImage = [UIImage imageNamed:@"image"]; UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
10. [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
11. cornerRadius:50] addClip];
12. [anotherImage drawInRect:imageView.bounds];
13. imageView.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
14. [self.view addSubview:imageView];
你是怎样封装一个view的
1. 1). 可以通过纯代码或许xib的方法来封装子控件 2). 建立一个跟view相关的模型,然后将模型数据传给view,通过模型上的数据给view的子控件赋值 /**
2. * 纯代码初始化控件时必定会走这个方法
3. */ - (instancetype)initWithFrame:(CGRect)frame { if(self = [super initWithFrame:frame]) {
4. [self setupUI];
5. } return self;
6. } /**
7. * 通过xib初始化控件时必定会走这个方法
8. */ - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) {
9. [self setupUI];
10. } return self;
11. }
12.
13. - (void)setupUI { // 初始化代码 }
HTTP协议中 POST 方法和 GET 方法有那些差异?
- GET用于向服务器央求数据,POST用于提交数据
- GET央求,央求参数拼接方法暴露在地址栏,而POST央求参数则放在央求体里面,因此GET央求不适合用于验证暗码等操作
- GET央求的URL有长度捆绑,POST央求不会有长度捆绑
请简略的介绍下APNS发送系统消息的机制
APNS优势:杜绝了类似安卓那种为了承受奉告不断在后台唤醒程序保持长衔接的行为,由iOS系统和APNS进行长衔接代替。
APNS的原理:
1). 应用在奉告中心注册,由iOS系统向APNS央求回来设备令牌(device Token)
2). 应用程序接收到设备令牌并发送给自己的后台服务器
3). 服务器把要推送的内容和设备发送给APNS
4). APNS根据设备令牌找到设备,再由iOS根据APPID把推送内容展示
77. ios开发逆向传值的几种方法收拾
榜首种:署理传值
1. 第二个控制器: @protocol WJSecondViewControllerDelegate - (void)changeText:(NSString*)text; @end @property(nonatomic,assign)iddelegate;
2.
3. - (IBAction)buttonClick:(UIButton*)sender {
4. _str = sender.titleLabel.text;
5. [self.delegate changeText:sender.titleLabel.text];
6. [self.navigationController popViewControllerAnimated:YES];
7. }
8.
9. 榜首个控制器:
10.
11. - (IBAction)pushToSecond:(id)sender {
12. WJSecondViewController *svc = [[WJSecondViewController alloc]initWithNibName:@"WJSecondViewController" bundle:nil];
13. svc.delegate = self;
14. svc.str = self.navigationItem.title;
15. [self.navigationController pushViewController:svc animated:YES];
16. [svc release];
17. }
18. - (void)changeText:(NSString *)text{ self.navigationItem.title = text;
19. }
第二种:奉告传值
1. 榜首个控制器: //注册监听奉告 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitDataForModel:) name:@"NOV" object:nil];
2. - (void)limitDataForModel:(NSNotification *)noti{ self.gamesInfoArray = noti.object;
3. }
4.
5. 第二个控制器: //发送奉告 [[NSNotificationCenter defaultCenter] postNotificationName:@"NOV" object:gameArray];
第三种:单例传值
1. Single是一个单例类,并且有一个字符串类型的特征titleName
2. 在第二个控制器:
3.
4. - (IBAction)buttonClick:(UIButton*)sender {
5. Single *single = [Single sharedSingle];
6. single.titleName = sender.titleLabel.text;
7. [self.navigationController popViewControllerAnimated:YES];
8. }
9.
10. 榜首个控制器:
11.
12. - (void)viewWillAppear:(BOOL)animated{
13. [super viewWillAppear:animated];
14. Single *single = [Single sharedSingle]; self.navigationItem.title = single.titleName;
15. }
第四种:block传值
1. 第二个控制器: @property (nonatomic,copy) void (^changeText_block)(NSString*);
2. - (IBAction)buttonClick:(UIButton*)sender {
3. _str = sender.titleLabel.text; self.changeText_block(sender.titleLabel.text);
4. [self.navigationController popViewControllerAnimated:YES];
5. }
6.
7. 榜首个控制器:
8.
9. - (IBAction)pushToSecond:(id)sender {
10. WJSecondViewController *svc = [[WJSecondViewController alloc]initWithNibName:@"WJSecondViewController" bundle:nil];
11. svc.str = self.navigationItem.title;
12. [svc setChangeText_block:^(NSString *str) {
13. >self.navigationItem.title = str;
14. }];
15. [self.navigationController pushViewController:svc animated:YES];
16. }
第五种:extern传值
1. 第二个控制器: extern NSString *btn;
2. - (IBAction)buttonClick:(UIButton*)sender {
3. btn = sender.titleLabel.text;
4. [self.navigationController popViewControllerAnimated:YES];
5. }
6.
7. 榜首个控制器: NSString *btn = nil;
8. - (void)viewWillAppear:(BOOL)animated{
9. [super viewWillAppear:animated]; self.navigationItem.title = btn;
10. }
第六种:KVO传值
1. 榜首个控制器:
2.
3. - (void)viewDidLoad {
4. [super viewDidLoad];
5. _vc =[[SecondViewController alloc]init]; //self监听vc里的textValue特征 [_vc addObserver:self forKeyPath:@"textValue" options:0 context:nil];
6. }
7.
8. 第二个控制器:
9.
10. - (IBAction)buttonClicked:(id)sender { self.textValue = self.textField.text;
11. [self.navigationController popViewControllerAnimated:YES];
12. }
78. 浅谈iOS开发中方法推延实施的几种方法
Method1. performSelector方法
Method2. NSTimer定时器
Method3. NSThread线程的sleep
Method4. GCD
共用推延实施方法
- (void)delayMethod{ NSLog(@”delayMethodEnd”);
Method1: performSelector
1. [self performSelector:@selector(delayMethod) withObject:nil/*可传任意类型参数*/ afterDelay:2.0];`
2. 注:此方法是一种非阻塞的实施方法,未找到撤销实施的方法。
3.
4. > 程序作业结束
5. > 2015-08-31 10:56:59.361 CJDelayMethod[1080:39604] delayMethodStart2015-08-31 10:56:59.363 CJDelayMethod[1080:39604] nextMethod2015-08-31 10:57:01.364 CJDelayMethod[1080:39604] delayMethodEnd
Method2: NSTimer定时器
1. NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];`
2. 注:此方法是一种非阻塞的实施方法,
3. 撤销实施方法:`- (void)invalidate;`即可
4.
5. > 程序作业结束
6. > 2015-08-31 10:58:10.182 CJDelayMethod[1129:41106] delayMethodStart2015-08-31 10:58:10.183 CJDelayMethod[1129:41106] nextMethod2015-08-31 10:58:12.185 CJDelayMethod[1129:41106] delayMethodEnd
Method3: NSThread线程的sleep
1. [NSThread sleepForTimeInterval:2.0];
2. 注:此方法是一种阻塞实施方法,建议放在子线程中实施,否则会卡住界面。但有时仍是需求阻塞实施,如进入欢迎界面需求熟睡3秒才进入主界面时。
3. 没有找到撤销实施方法。
4.
5. > 程序作业结束
6. > 2015-08-31 10:58:41.501 CJDelayMethod[1153:41698] delayMethodStart2015-08-31 10:58:43.507 CJDelayMethod[1153:41698] nextMethod
Method4: GCD
1. __block ViewController/*主控制器*/ *weakSelf = self; dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0/*推延实施时间*/ * NSEC_PER_SEC));
2.
3. dispatch_after(delayTime, dispatch_get_main_queue(), ^{
4. [weakSelf delayMethod];
5. });
6.
7. 注:此方法可以在参数中选择实施的线程,是一种非阻塞实施方法。没有找到撤销实施方法。
8.
9. > 程序作业结束
10. > 2015-08-31 10:59:21.652 CJDelayMethod[1181:42438] delayMethodStart2015-08-31 10:59:21.653 CJDelayMethod[1181:42438] nextMethod2015-08-31 10:59:23.653 CJDelayMethod[1181:42438] delayMethodEnd
1. 无缺代码参见:
2.
3. > // > // ViewController.m > // CJDelayMethod > // > // Created by 陈杰 on 8/31/15. > // Copyright (c) 2015 chenjie. All rights reserved. > // >
4. > # import "ViewController.h" >
5. > @interface ViewController () > @property (nonatomic, strong) NSTimer *timer;
6. > @end > @implementation ViewController* >
7. > *`- (void)viewDidLoad { `*
8. >
9. > *` [super viewDidLoad]; `*
10. >
11. > *` NSLog(@"delayMethodStart"); `*
12. >
13. > *` [self methodOnePerformSelector];// `* >
14. > *` [self methodTwoNSTimer];// `* >
15. > *` [self methodThreeSleep];//`* >
16. > *` [self methodFourGCD]; `*
17. >
18. > *` NSLog(@"nextMethod");`*
19. >
20. > *`}`*
21. >
22. > *`- (void)methodFiveAnimation{ `*
23. >
24. > *` [UIView animateWithDuration:0 delay:2.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ } completion:^(BOOL finished) { `*
25. >
26. > *` [self delayMethod]; `*
27. >
28. > *` }];`*
29. >
30. > *`}`
31. > `- (void)methodFourGCD{ `*
32. >
33. > *` __block ViewController`*`weakSelf = self; dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)); dispatch_after(delayTime, dispatch_get_main_queue(), ^{ `
34. >
35. > ` [weakSelf delayMethod]; `
36. >
37. > ` });`
38. >
39. > `}`
40. >
41. > `- (void)methodThreeSleep{ `
42. >
43. > ` [NSThread sleepForTimeInterval:2.0];`
44. >
45. > `}`
46. >
47. > `- (void)methodTwoNSTimer{`
48. >
49. > ` NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];`
50. >
51. > `}`
52. >
53. > `- (void)methodOnePerformSelector{`
54. >
55. > ` [self performSelector:@selector(delayMethod) withObject:nil/*可传任意类型参数*/ afterDelay:2.0];`
56. >
57. > `}`
58. >
59. > `- (void)delayMethod{`
60. >
61. > ` NSLog(@"delayMethodEnd");`
62. >
63. > `}`
64. > `- (void)didReceiveMemoryWarning { `
65. >
66. > ` [super didReceiveMemoryWarning]; `
67. >
68. > ` // Dispose of any resources that can be recreated.` >
69. > `}`
70. >
71. > `@end`
NSPersistentStoreCoordinator , NSManaged0bjectContext 和NSManaged0bject中的那些需求在线程中创建或许传递
答:NSPersistentStoreCoordinator是耐久化存储和谐者,首要用于和谐保管方针上下文和耐久化存储区之间的联络。NSManagedObjectContext运用和谐者的保管方针模型将数据保存到数据库,或查询数据。
您是否做过一部的网络处理和通讯方面的作业?假设有,能具体介绍一下结束战略么?
答:运用NSOperation发送异步网络央求,运用NSOperationQueue处理线程数目及优先级,底层是用NSURLConnetion
你运用过Objective-C的作业时编程(Runtime Programming)么?假设运用过,你用它做了什么?你还能记住你所运用的相关的头文件或许某些方法的称谓吗?
答:Objecitve-C的重要特性是Runtime(作业时),在#import下能看到相关的方法,用过objc_getClass()和class_copyMethodList()获取过私有API;运用
Method method1 = class_getInstanceMethod(cls, sel1);
Method method2 = class_getInstanceMethod(cls, sel2);
method_exchangeImplementations(method1, method2);
代码沟通两个方法,在写unit test时运用到。
Core最初的系列的内容。是否运用过CoreAnimation和CoreGraphics。UI结构和CA,CG结构的联络是什么?别离用CA和CG做过些什么动画或许图画上的内容。(有需求的话还可以涉及Quartz的一些内容)
答:UI结构的底层有CoreAnimation,CoreAnimation的底层有CoreGraphics。
UIKit |
---|
Core Animation |
Core Graphics |
Graphics Hardware |
运用CA做过menu菜单的展开收起(太逊了) |
是否运用过CoreText或许CoreImage等?假设运用过,请谈谈你运用CoreText或许CoreImage的体会。
答:CoreText可以处理凌乱文字内容排版问题。CoreImage可以处理图片,为其添加各种作用。体会是很健壮,挺凌乱的。
主动开释池是什么,怎样作业
答:当您向一个方针发送一个autorelease消息时,Cocoa就会将该方针的一个引用放入到最新的主动开释.它仍然是个OC的方针,因此主动开释池定义的作用域内的其它方针可以向它发送消息。当程序实施到作用域结束的方位时,主动开释池就会被开释,池中的全部方针也就被开释。
NSNotification和KVO的差异和用法是什么?什么时分应该运用奉告,什么时分应该运用KVO,它们的结束上有什么差异吗?假设用protocol和delegate(或许delegate的Array)来结束类似的功用或许吗?假设或许,会有什么潜在的问题?假设不能,为什么?(尽管protocol和delegate这种东西面试现已面烂了…)
答:NSNotification是奉告方法在iOS的结束,KVO的全称是键值查询(Key-value observing),其是根据KVC(key-value coding)的,KVC是一个通过特征名访问特征变量的机制。例如将Module层的改动,奉告到多个Controller方针时,可以运用NSNotification;假设是只需求查询某个方针的某个特征,可以运用KVO。
关于托付方法,在规划方法中是方针适配器方法,其是delegate是指向某个方针的,这是1对1的联络,而在奉告方法中,往往是一对多的联络。托付方法,从技术上可以现在改动delegate指向的方针,但不建议这样做,会让人迷惑,假设一个delegate方针不断改动,指向不同的方针。
你用过NSOperationQueue么?假设用过或许了解的话,你为什么要运用NSOperationQueue,结束了什么?请描绘它和G.C.D的差异和类似的当地(提示:可以从两者的结束机制和适用规模来描绘)。
答:运用NSOperationQueue用来处理子类化的NSOperation方针,控制其线程并发数目。GCD和NSOperation都可以结束对线程的处理,差异是 NSOperation和NSOperationQueue是多线程的面向方针抽象。项目中运用NSOperation的利益是NSOperation是对线程的高度抽象,在项目中运用它,会使项目的程序结构更好,子类化NSOperation的规划思路,是具有面向方针的利益(复用、封装),使得结束是多线程支撑,而接口简略,建议在凌乱项目中运用。
项目中运用GCD的利益是GCD本身十分简略、易用,关于不凌乱的多线程操作,会节省代码量,而Block参数的运用,会是代码更为易读,建议在简略项目中运用。
已然提到G.C.D,那么问一下在运用G.C.D以及block时要留心些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么差异,需求留心些什么?
答:运用block是要留心,若将block做函数参数时,需求把它放到终究,GCD是Grand Central Dispatch,是一个对线程开源类库,而Block是闭包,是可以读取其他函数内部变量的函数。
关于Objective-C,你认为它最大的利益和最大的缺少是什么?关于缺少之处,现在有没有可用的方法绕过这些缺少来结束需求。假设可以的话,你有没有考虑或许实践过从头结束OC的一些功用,假设有,具体会怎样做?
答:最大的利益是它的作业时特性,缺少是没有命名空间,关于命名冲突,可以运用长命名法或特别前缀处理,假设是引进的第三方库之间的命名冲突,可以运用link指令及flag处理冲突。
你结束过一个结构或许库以供别人运用么?假设有,请谈一谈构建结构或许库时分的阅历;假设没有,请想象和规划结构的public的API,并指出大约需求怎样做、需求留心一些什么方面,来使别人容易地运用你的结构。
答:抽象和封装,便当运用。首要是对问题有充分的了解,比如构建一个文件解压紧缩结构,从运用者的角度启航,只需注重发送给结构一个解压央求,结构结束凌乱文件的解压操作,并且在恰当的时分奉告给是哦难过者,如解压结束、解压犯错等。在结构内部去构建方针的联络,通过抽象让其更为健旺、便于更改。其次是API的阐明文档。
二、 第三方结构
AFNetworking 底层原理分析
AFNetworking首要是对NSURLSession和NSURLConnection(iOS9.0抛弃)的封装,其间首要有以下类:
1). AFHTTPRequestOperationManager:内部封装的是 NSURLConnection, 担任发送网络央求, 运用最多的一个类。(3.0抛弃)
2). AFHTTPSessionManager:内部封装是 NSURLSession, 担任发送网络央求,运用最多的一个类。
3). AFNetworkReachabilityManager:实时监测网络情况的东西类。当时的网络环境发生改动之后,这个东西类就可以检测到。
4). AFSecurityPolicy:网络安全的东西类, 首要是针对 HTTPS 服务。
5). AFURLRequestSerialization:序列化东西类,基类。上传的数据转换成JSON格式
(AFJSONRequestSerializer).运用不多。
6). AFURLResponseSerialization:反序列化东西类;基类.运用比较多:
7). AFJSONResponseSerializer; JSON解析器,默许的解析器.
8). AFHTTPResponseSerializer; 万能解析器; JSON和XML之外的数据类型,直接回来二进
制数据.对服务器回来的数据不做任何处理.
9). AFXMLParserResponseSerializer; XML解析器;
描绘下SDWebImage里面给UIImageView加载图片的逻辑
SDWebImage 中为 UIImageView 供应了一个分类UIImageView+WebCache.h, 这个分类中有一个最常用的接口sd_setImageWithURL:placeholderImage:,会在实在图片出现前会先闪现占位图片,当实在图片被加载出来后再替换占位图片。
加载图片的进程大致如下:
1.首要会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以url 作为数据的索引先在内存中寻找是否有对应的缓存
2.假设缓存未找到就会运用通过MD5处理过的key来继续在磁盘中查询对应的数据, 假设找到了, 就会把磁盘中的数据加载到内存中,并将图片闪现出来
3.假设在内存和磁盘缓存中都没有找到,就会向长途服务器发送央求,开端下载图片
4.下载后的图片会参与缓存中,并写入磁盘中
5.整个获取图片的进程都是在子线程中实施,获取到图片后回到主线程将图片闪现出来
SDWebImage原理:
调用类别的方法:
- 从内存(字典)中找图片(当这个图片在本次运用程序的进程中现已被加载过),找到直接运用。
- 从沙盒中找(当这个图片在之前运用程序的进程中被加载过),找到运用,缓存到内存中。
- 从网络上获取,运用,缓存到内存,缓存到沙盒。
友盟核算接口核算的全部功用
APP发起速度,APP逗留页面时间等
三、算法
1.不用中心变量,用两种方法沟通A和B的值
1. // 1.中心变量 void swap(int a, int b) { int temp = a;
2. a = b;
3. b = temp;
4. } // 2.加法 void swap(int a, int b) {
5. a = a + b;
6. b = a - b;
7. a = a - b;
8. } // 3.异或(相同为0,不同为1\. 可以了解为不进位加法) void swap(int a, int b) {
9. a = a ^ b;
10. b = a ^ b;
11. a = a ^ b;
12. }
2.求最大公约数
1. /** 1.直接遍历法 */ int maxCommonDivisor(int a, int b) { int max = 0; for (int i = 1; i <=b; i++) { if (a % i == 0 && b % i == 0) {
2. max = I;
3. }
4. } return max;
5. } /** 2.曲折相除法 */ int maxCommonDivisor(int a, int b) { int r; while(a % b > 0) {
6. r = a % b;
7. a = b;
8. b = r;
9. } return b;
10. } // 扩展:最小公倍数 = (a * b)/最大公约数
3.模仿栈操作
1. /**
2. * 栈是一种数据结构,特征:先进后出
3. * 练习:运用全局变量模仿栈的操作
4. */ #include #include #include //保护全局变量:在全局变量前加static后,这个全局变量就只能在本文件中运用 static int data[1024];//栈最多能保存1024个数据 static int count = 0;//现在现已放了多少个数(相当于栈顶方位) //数据入栈 push void push(int x){
5. assert(!full());//避免数组越界 data[count++] = x;
6. } //数据出栈 pop int pop(){
7. assert(!empty()); return data[--count];
8. } //检查栈顶元素 top int top(){
9. assert(!empty()); return data[count-1];
10. } //查询栈满 full bool full() { if(count >= 1024) { return 1;
11. } return 0;
12. } //查询栈空 empty bool empty() { if(count <= 0) { return 1;
13. } return 0;
14. } int main(){ //入栈 for (int i = 1; i <= 10; i++) {
15. push(i);
16. } //出栈 while(!empty()){ printf("%d ", top()); //栈顶元素 pop(); //出栈 } printf("\n"); return 0;
17. }
4.排序算法
1. 选择排序、冒泡排序、刺进排序三种排序算法可以总结为如下:
2.
3. * 都将数组分为已排序部分和未排序部分。 1\. 选择排序将已排序部分定义在左端,然后选择未排序部分的最小元素和未排序部分的榜首个元素沟通。 2\. 冒泡排序将已排序部分定义在右端,在遍历未排序部分的进程实施沟通,将最大元素沟通到最右端。 3\. 刺进排序将已排序部分定义在左端,将未排序部分元的榜首个元素刺进到已排序部分适合的方位。
选择排序*
【选择排序】:最值出现在开始端
第1趟:在n个数中找到最小(大)数与榜首个数沟通方位
第2趟:在剩余n-1个数中找到最小(大)数与第二个数沟通方位
重复这样的操作…依次与第三个、第四个…数沟通方位
第n-1趟,毕竟可结束数据的升序(降序)摆放。
voidselectSort(int * arr, intlength) {
for (inti = 0;i < length - 1;i++) {
//趟数for(intj=i+1;j<length;j++){//比较次数
if(arr[i]>arr[j]){
inttemp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
冒泡排序
【冒泡排序】:相邻元素两两比较,比较完一趟,最值出现在结尾
第1趟:依次比较相邻的两个数,不断沟通(小数放前,大数放后)逐个推进,最值终究出现在第n个元素方位
第2趟:依次比较相邻的两个数,不断沟通(小数放前,大数放后)逐个推进,最值终究出现在第n-1个元素方位
第n-1趟:依次比较相邻的两个数,不断沟通(小数放前,大数放后)逐个推进,最值终究出现在第2个元素方位
voidbublleSort(int * arr, intlength) {
for (inti = 0;i < length - 1;i++) {
//趟数for(intj=0;j<length-i-1;j++){
//比较次数if(arr[j]>arr[j+1]){
inttemp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
5.折半查找(二分查找)
1. /**
2. * 折半查找:优化查找时间(不用遍历全部数据)
3. *
4. * 折半查找的原理:
5. * 1> 数组有必要是有序的
6. * 2> 有必要已知min和max(知道规模)
7. * 3> 动态核算mid的值,取出mid对应的值进行比较
8. * 4> 假设mid对应的值大于要查找的值,那么max要变小为mid-1
9. * 5> 假设mid对应的值小于要查找的值,那么min要变大为mid+1
10. *
11. */ // 已知一个有序数组, 和一个key, 要求从数组中找到key对应的索引方位 int findKey(int *arr, int length, int key) { int min = 0, max = length - 1, mid; while (min <= max) {
12. mid = (min + max) / 2; //核算中心值 if (key > arr[mid]) {
13. min = mid + 1;
14. } else if (key < arr[mid]) {
15. max = mid - 1;
16. } else { return mid;
17. }
18. } return -1;
19. }
四、编码格式(优化细节)
1.在 Objective-C 中,enum 建议运用NS_ENUM和NS_OPTIONS宏来定义枚举类型。
1. //定义一个枚举(比较严密) typedef NS_ENUM(NSInteger, BRUserGender) {
2. BRUserGenderUnknown, // 不知道 BRUserGenderMale, // 男性 BRUserGenderFemale, // 女人 BRUserGenderNeuter // 无性 }; @interface BRUser : NSObject @property (nonatomic, readonly, copy) NSString *name; @property (nonatomic, readonly, assign) NSUInteger age; @property (nonatomic, readonly, assign) BRUserGender gender;
3.
4. - (instancetype)initWithName:(NSString *)name age:(NSUInteger)age gender:(BRUserGender)gender; @end //阐明: //已然该类中现已有一个“初始化方法” ,用于设置 name、age 和 gender 的初始值: 那么在规划对应 @property 时就应该尽量运用不行变的方针:其三个特征都应该设为“只读”。用初始化方法设置好特征值之后,就不能再改动了。 //特征的参数应该按照下面的次序摆放: (原子性,读写,内存处理)
2.避免运用C言语中的底子数据类型,建议运用 Foundation 数据类型,对应联络如下:
int -> NSInteger
unsigned -> NSUInteger
float -> CGFloat
动画时间 -> NSTimeInterval
五、其它知识点
HomeKit,是苹果2014年发布的智能家居渠道。
什么是 OpenGL、Quartz 2D?
Quatarz 2d 是Apple供应的底子图形东西库。仅仅适用于2D图形的制造。
OpenGL,是一个跨渠道的图形开发库。适用于2D和3D图形的制造。
ffmpeg结构:
ffmpeg 是音视频处理东西,既有音视频编码解码功用,又可以作为播放器运用。
谈谈 UITableView 的优化
1). 正确的复用cell;
2). 规划共同标准的Cell;
3). 提前核算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频频的方法;
4). 异步制造,遇到凌乱界面,遇到功用瓶颈时,或许就是突破口;
5). 滑动时按需加载,这个在许多图片展示,网络加载的时分很管用!
6). 减少子视图的层级联络;
7). 尽量使全部的视图不通明化以及做切圆操作;
8). 不要动态的add 或许 remove 子控件。最好在初始化时就添加完,然后通过hidden来控制是否闪现;
9). 运用调试东西分析问题。
怎样实施cell的动态的行高
假设期望每条数据闪现本身的行高,有必要设置两个特征,1.预估行高,2.自定义行高。
设置预估行高 tableView.estimatedRowHeight = 200。
设置定义行高 tableView.estimatedRowHeight = UITableViewAutomaticDimension。
假设要让自定义行高有用,有必要让容器视图有一个自下而上的捆绑。
说说你对 block 的了解
栈上的主动拷贝到堆上,block 的特征修饰符是 copy,循环引用的原理和处理计划。
block的循环引用;block的代码结束;为什么会构成循环引用;block是怎样强引用self的;
什么是野指针、空指针?
野指针:不知道指向了哪里的指针叫野指针。即指针指向不承认,指针存的地址是一个废物值,未初始化。
空指针:不指向任何方位的指针叫空指针。即指针没有指向,指针存的地址是一个空地址,NULL。
什么是 OOA / OOD / OOP ?
OOA(Object Oriented Analysis) –面向方针分析
OOD(Object Oriented Design) –面向方针规划
OOP(Object Oriented Programming)–面向方针编程
多线程是什么
多线程是个凌乱的概念,按字面意思是同步结束多项任务,前进了资源的运用效率,从硬件、操作系统、应用软件不同的角度去看,多线程被赋予不同的内在,关于硬件,现在市面上大都的CPU都是多核的,多核的CPU运算多线程更为超卓;从操作系统角度,是多任务,现在用的干流操作系统都是多任务的,可以一边听歌、一边写博客;关于应用来说,多线程可以让应用有更快的回应,可以在网络下载时,一起呼应用户的触摸操作。在iOS应用中,对多线程开始的了解,就是并发,它的含义是本来先做烧水,再摘菜,再炒菜的作业,会变成烧水的一起去摘菜,终究去炒菜。
iOS 中的多线程
iOS中的多线程,是Cocoa结构下的多线程,通过Cocoa的封装,可以让咱们更为便当的运用线程,做过C++的同学或许会对线程有更多的了解,比如线程的创建,信号量、同享变量有知道,Cocoa结构下会便当许多,它对线程做了封装,有些封装,可以让咱们创建的方针,本身便具有线程,也就是线程的方针化抽象,然后减少咱们的工程,供应程序的健旺性。
GCD是(Grand Central Dispatch)的缩写 ,从系统等级供应的一个易用地多线程类库,具有作业时的特征,能充分运用多核心硬件。GCD的API接口为C言语的函数,函数参数中大都有Block,关于Block的运用参看这儿,为咱们供应健壮的“接口”,关于GCD的运用参见本文
NSOperation与Queue
NSOperation是一个抽象类,它封装了线程的细节结束,咱们可以通过子类化该方针,加上NSQueue来同面向方针的思想,处理多线程程序。具体可参看这儿:一个根据NSOperation的多线程网络访问的项目。
NSThread
NSThread是一个控制线程实施的方针,它不如NSOperation抽象,通过它咱们可以便当的得到一个线程,并控制它。但NSThread的线程之间的并发控制,是需求咱们自己来控制的,可以通过NSCondition结束。
参看 iOS多线程编程之NSThread的运用
其他多线程
在Cocoa的结构下,奉告、Timer和异步函数等都有运用多线程,(待补充).
在项目什么时分选择运用GCD,什么时分选择NSOperation?
项目中运用NSOperation的利益是NSOperation是对线程的高度抽象,在项目中运用它,会使项目的程序结构更好,子类化NSOperation的规划思路,是具有面向方针的利益(复用、封装),使得结束是多线程支撑,而接口简略,建议在凌乱项目中运用。
项目中运用GCD的利益是GCD本身十分简略、易用,关于不凌乱的多线程操作,会节省代码量,而Block参数的运用,会是代码更为易读,建议在简略项目中运用。
KVO,NSNotification,delegate及block差异
- KVO就是cocoa结构结束的查询者方法,一般同KVC分配运用,通过KVO可以监测一个值的改动,比如View的高度改动。是一对多的联络,一个值的改动会奉告全部的查询者。
- NSNotification是奉告,也是一对多的运用场景。在某些情况下,KVO和NSNotification是相同的,都是情况改动之后奉告对方。NSNotification的特征,就是需求被查询者先主动宣告奉告,然后查询者注册监听后再来进行呼应,比KVO多了发送奉告的一步,但是其利益是监听不局限于特征的改动,还可以对多种多样的情况改动进行监听,监听规模广,运用也更活络。
- delegate 是署理,就是我不想做的作业交给别人做。比如狗需求吃饭,就通过delegate奉告主人,主人就会给他煮饭、盛饭、倒水,这些操作,这些狗都不需求关心,只需求调用delegate(署理人)就可以了,由其他类结束所需求的操作。所以delegate是1对1联络。
- block是delegate的另一种方法,是函数式编程的一种方法。运用场景跟delegate相同,比较delegate更活络,并且署理的结束更直观。
- KVO一般的运用场景是数据,需求是数据改动,比如股票价格改动,咱们一般运用KVO(查询者方法)。delegate一般的运用场景是行为,需求是需求别人帮我做一件作业,比如生意股票,咱们一般运用delegate。
Notification一般是进行全局奉告,比如利好消息一出,奉告咱们去买入。delegate是强相关,就是托付和署理两边互相知道,你托付别人买股票你就需求知道经纪人,经纪人也不要知道自己的顾客。Notification是弱相关,利好消息宣告,你不需求知道是谁发的也可以做出相应的反响,同理发消息的人也不需求知道接收的人也可以正常宣告消息。
将一个函数在主线程实施的4种方法
1. * GCD方法,通过向主线程队伍发送一个block块,使block里的方法可以在主线程中实施。 dispatch_async(dispatch_get_main_queue(), ^{ //需求实施的方法 });
2.
3.
4. * NSOperation 方法 NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主队伍 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ //需求实施的方法 }];
5. [mainQueue addOperation:operation];
6.
7.
8. * NSThread 方法
9.
10. [self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
11.
12. [self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
13.
14. [[NSThread mainThread] performSelector:@selector(method) withObject:nil];
15.
16.
17. * RunLoop方法
18.
19. [[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];
怎样让计时器调用一个类方法
- 计时器只能调用实例方法,但是可以在这个实例方法里面调用静态方法。
- 运用计时器需求留心,计时器必定要参与RunLoop中,并且选好model才干作业。scheduledTimerWithTimeInterval方法创建一个计时器并参与到RunLoop中所以可以直接运用。
- 假设计时器的repeats选择YES阐明这个计时器会重复实施,必定要在适合的时机调用计时器的invalid。不能在dealloc中调用,因为一旦设置为repeats 为yes,计时器会强持有self,导致dealloc永久不会被调用,这个类就永久无法被开释。比如可以在viewDidDisappear中调用,这样当类需求被回收的时分就可以正常进入dealloc中了。
1. [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
2.
3. -(void)timerMethod
4. { //调用类方法 [[self class] staticMethod];
5. }
6.
7. -(void)invalid
8. {
9. [timer invalid];
10. timer = nil;
11. }
怎样重写类方法
○1、在子类中结束一个同基类名字相同的静态方法
○2、在调用的时分不要运用类名调用,而是运用[self class]的方法调用。原理,用类名调用是早绑定,在编译期绑定,用[self class]是晚绑定,在作业时决议调用哪个方法。
NSTimer创建后,会在哪个线程作业
○用scheduledTimerWithTimeInterval创建的,在哪个线程创建就会被参与哪个线程的RunLoop中就作业在哪个线程
○自己创建的Timer,参与到哪个线程的RunLoop中就作业在哪个线程。
id和NSObject*的差异
○id是一个 objc_object 结构体指针,定义是
typedef struct objc_object *id
○id可以了解为指向方针的指针。全部oc的方针 id都可以指向,编译器不会做类型检查,id调用任何存在的方法都不会在编译阶段报错,当然假设这个id指向的方针没有这个方法,该溃散仍是会溃散的。
○NSObject *指向的有必要是NSObject的子类,调用的也只能是NSObjec里面的方法否则就要做强制类型转换。
○不是全部的OC方针都是NSObject的子类,还有一些继承自NSProxy。NSObject *可指向的类型是id的子集。
static关键字的作用
答复一:
1.在函数体内定义的static他的作用域为该函数体,该变量在内存中只被分配一次,因此,其值在下次调用时仍保持前次的值不变;
2.在模块内的static全局变量可以被模块内全部函数访问,但是不能被模块外的其他函数访问;
3.在模块内的staic全局变量可以被这一模块内的其他函数调用,这个函数的运用规模被捆绑在这个模块内;
4.在类中的static成员变量归于整个类所具有,对类的全部方针只要一份拷贝,也就是说只要是该类的方针,那么该方针的中被static修饰的成员变量都指向同一块地址。
答复二:
修饰局部变量:
1.延伸局部变量的生命周期,程序结束才会销毁。
2.局部变量只会生成一份内存,只会初始化一次。
3.改动局部变量的作用域。
修饰全局变量:
1.只能在本文件中访问,批改全局变量的作用域,生命周期不会改
2.避免重复定义全局变量
在OC中static关键字运用误区
1.运用static修饰实例变量是不被答应的
2.运用static修饰了方法,也是差错的
参看:
怎样正确运用const,static,extern
OC中 static 与 const 的作用
运用 Swift 言语编程的优缺陷总的来说,我认为运用 Swift 来作为编程言语的利益仍是要远远大于缺陷的,并且许多缺陷苹果也在逐步改善。
利益:
1、简练的语法
2、更强的类型安全
3、函数式编程的支撑
Swift 言语本身供应了对函数式编程的支撑。
Objc 本身是不支撑的,但是可以通过引进 ReactiveCocoa 这个库来支撑函数式编程。
4、编写 OS X 下的主动化脚本
缺陷
1、App体积变大
运用Swift 后, App 体积大约添加 5-8 M 左右,对体积巨细活络的慎用。
体积变大的原因是因为 Swift 还在改动,所以 Apple 没有在 iOS 系统里放入 Swift 的作业库,反而是每个 App 里都要包含其对应的 Swift 作业库。
2、Xcode 支撑不够好
假设你是运用 Xcode常常卡住或许溃散想必你是必定碰到过了,这个是现在运用 Swift 最让人头疼的作业,即使是到现在XCode 9, 有时分也会遇到这种问题,所以要看你的承受力了……
3、第三方库的支撑不够多
现在的确 Swift 编写的第三方库的确不多,但可以通过桥接的方法来运用 Objc 的三方库,底子上没有太大问题。现在现已改善许多了…
4、言语版别更新带来的编译问题
言语本身还在开展,所以每次版别更新后都会出现编译不过的情况(至少到现在为止仍是),但是自从 4.0 版别发布后,改动没有 beta 时分那么大了,并且根据 Xcode 提示底子就可以处理语法改动导致的编译问题了。