一、多线程开发的理解以及iOS中有几种实现多线程的方法?
好处:
1、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载;
2、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好。
缺点:
1、大量的线程降低代码的可读性;
2、更多的线程需要更多的内存空间;
3、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:
1、NSThread(两种创建方式)[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
2、NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//这个block语句块在子线程中执行
}
3、Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
不显示的创建线程的方法:用NSObject的类方法 performSelectorInBackground:withObject: 创建一个线程:[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
二、线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程。
异步:同时去做两件或者多件事。比如边听歌边看报。
实现:原子操作(atomic)、加锁(NSLock、NSRecursive、NSConditionLock)、@synchronized GCD串行队列,GCD当中的屏障,NSOperationQueue设置最大并发数为1
三、iOS本地数据存储都有哪几种方式?iOS如何实现复杂对象的存储?
NSKeyedArchiver(归档)采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。
1.NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。
2.Write写入方式:永久保存在磁盘中。
3.SQLite(FMDB、CoreData)
NSCoding + NSKeyedArchiver实现复杂对象的存储。
四、怎样实现一个singleton的类?
//第一种方式
static LOSingleton * shareInstance;
+( LOSingleton *)sharedInstance{
@synchronized(self){//这个东西其实就是一个加锁。如果self 其他线程访问,则会阻塞。这样做一般是用来对单例进行一个死锁的保护
if (shareInstance == nil) {
shareInstance = [[super allocWithZone:NULL] init];
}
}
return shareInstance;
}
//第二种方式
+ (LOSingleton *) sharedInstance
{
static LOSingleton *sharedInstance = nil ;
static dispatch_once_t onceToken; // 锁
dispatch_once (& onceToken, ^ { // 最多调用一次
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
五、什么是安全释放?
在对象release之后把指针置为nil。
六、简述你对UIView、UIWindow和CALayer的理解
UIView继承于UIResponder, UIResponder继承于NSObject,UIView可以响应用户事件。CALayer继承于NSObject,所以CALayer不能响应事件。UIView构建界面,UIView侧重于对内容的管理,CALayer侧重于对内容的绘制。UIView是用来显示内容的,可以处理用户事件;CALayer是用来绘制内容的,对内容进行动画处理,依赖与UIView来进行显示,不能处理用户事件。
七、什么是Protocol?什么是代理?写一个委托的interface?委托的property声明用什么属性?为什么?
协议提供了一组方法,但是并不负责实现,如果一个类遵循了某个协议,并且实现了协议里面的方法,那么我们称这个类就是遵循了某个协议的代理。属性的声明使用assign,防止出现循环引用的问题。
八、分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?
category类目:在不知道源码的情况下为一个类扩展方法;
extension:为一个类声明私有方法和变量。继承是创建了一个新的类,而类别只是对类的一个扩展,还是之前的类。类目的作用就是为已知的类添加方法。
九、Objective-C有私有方法么?私有变量呢?如多没有的话,有没有什么代替的方法?
objective-c – 类里面的方法只有两种, 静态方法和实例方法.
@private来修饰私有变量
OC中所有的实例变量默认都是私有的,所有的实例方法默认都是公有的。
十、objc中的减号与加号代表什么?
+静态方法,也叫类方法,-实例方法
十一、对于语句NSString* testObject = [[NSData alloc] init];testObject 在编译时和运行时分别是什么类型的对象?
编译的时候是NSString类型,运行的时候是NSData类型
十二、OC中是所有对象间的交互是如何实现的?
函数指针实现
十三、#import和#include的区别是什么?#import<> 跟 #import""有什么区别?
1、#import能避免头文件被重复包含的问题
2、一般来说,导入objective c的头文件时用#import,包含C/C++头文件时用#include。
3、#import 确定一个文件只能被导入一次,这使你在递归包含中不会出现问题。
4、#import<> 包含iOS框架类库里的类,#import""包含项目里自定义的类。
5、#import比起#include的好处就是它避免了重复引用的问题。所以在OC中我们基本用的都是import。
十四、Category是什么?扩展一个类的方式用继承好还是类目好?为什么?
Category是类目。用类目好,因为继承要满足a is a b的关系,而类目只需要满足a has a b的关系,局限性更小,你不用定义子类就能扩展一个类的功能,还能将类的定义分开放在不同的源文件里, 用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。
十五、类实例(成员)变量的@protected,@private,@public声明各有什么含义?
@protected:受保护的,该实例变量只能在该类和其子类内访问,其他类内不能访问。
@private:私有的,该实例变量只能在该类内访问,其他类内不能访问。
@public:共有的,该实例变量谁都可以访问。
十六、id声明的对象有什么特性?
1、没有 * 号
2、动态数据类型
3、可以指向任何类的对象(设置是nil),而不关心其具体类型
4、在运行时检查其具体类型
5、可以对其发送任何(存在的)消息
十七、内存管理的几条原则是什么?按照默认法则,哪些关键字生成的对象需要手动释放?哪些情况下不需要手动释放,会直接进入自动释放池?
内存管理的原则是:谁创建,谁释放;谁引用,谁管理。
遵循Cocoa Touch的使用原则;
内存管理主要要避免“过早释放”和“内存泄漏”,对于“过早释放”需要注意@property设置特性时,一定要用对特性关键字,对于“内存泄漏”,一定要申请了要负责释放,要细心。
1、当使用new、alloc或copy方法创建一个对象时,该对象引用计数器为1。如果不需要使用该对象,可以向其发送release或autorelease消息,在其使用完毕时被销毁。
2、如果通过其他方法获取一个对象,则可以假设这个对象引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release。
3、如果retain了某个对象,需要release或autorelease该对象,保持retain方法和release方法使用次数相等。
4、使用new、alloc、copy关键字生成的对象和retain了的对象需要手动释放。设置为autorelease的对象不需要手动释放,会直接进入自动释放池。
十八、属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
assign用于简单数据类型,如NSInteger,double,bool;
retain和copy用于对象;
readwrite是可读可写特性;需要生成getter方法和setter方法时;
readonly是只读特性 只会生成getter方法 不会生成setter方法 ,不希望属性在类外改变;
assign是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
retain表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
copy表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时;
nonatomic非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic。
十九、Objective-C如何对内存管理的,说说你的看法和解决方法?
Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
二十、那些关键字生成的对象 需要手动释放?
关键字alloc 或new 生成的对象需要手动释放
二十一、如何对iOS设备进行性能测试?
Profile-> Instruments ->Time Profiler
二十二、Category是什么?重写一个类的方式用继承好还是分类好?为什么?
Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。
二十三、Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
线程创建有三种方法:使用NSThread创建、使用 GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是 performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone
二十四、什么是Notification?什么时候用delegate,什么时候用Notification?
观察者模式,controller向defaultNotificationCenter添加自己的notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)。
delegate针对one-to-one关系,并且reciever可以返回值给sender,notification 可以针对one-to-one/many/none,reciever无法返回值给sender.所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。