iOS 基础笔试题
参考:https://www.jianshu.com/p/1d3496bc5bda
1、#import 跟#include、@class有什么区别?#import<> 跟 #import""又什么区别?
1.#import和#include都能完整地包含某个文件的内容,#import能防止同一个文件被包含多次
2.@class仅仅是声明一个类名,并不会包含类的完整声明;@class还能解决循环包含的问题
3.#import <> 用来包含系统自带的文件,#import “”用来包含自定义的文件
2、属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
readwrite:同时生成get方法和set方法的声明和实现
readonly:只生成get方法的声明和实现
assign:set方法的实现是直接赋值,用于基本数据类型
retain:set方法的实现是release旧值,retain新值,用于OC对象类型
copy:set方法的实现是release旧值,copy新值,用于NSString、block等类型
nonatomic:非原子性,set方法的实现不加锁(比atomic性能高)
3、写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name.
@property (nonatomic, retain) NSString *name; - (void)setName:(NSString *)name { if (_name != name) { [_name release]; _name = [name retain]; } } @property (nonatomic, copy) NSString *name; - (void)setName:(NSString *)name { if (_name != name) { [_name release]; _name = [name copy]; } }
4、对于语句NSString*obj = [[NSData alloc] init]; ,编译时和运行时obj分别是什么类型?
1.编译时是NSString类型
2.运行时是NSData类型
5、常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别?
常用OC类型:NSString、NSArray、NSDictionary、NSData、NSNumber等
OC对象需要手动管理内存,C的基本数据类型不需要管理内存
6、id 声明的变量有什么特性?
id声明的变量能指向任何OC对象
7、Objective-C如何对内存管理的,说说你的看法和解决方法?
每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁
通过retain可以让对象的计数器+1、release可以让对象的计数器-1
还可以通过autorelease pool管理内存
如果用ARC,编译器会自动生成管理内存的代码
8、内存管理的几条原则时什么?按照默认法则.哪些方法生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?
只要调用了alloc、copy、new方法产生了一个新对象,都必须在最后调用一次release或者autorelease
只要调用了retain,都必须在最后调用一次release或者autorelease
@property如果用了copy或者retian,就需要对不再使用的属性做一次release操作
如果用了ARC,另外讨论
9、看下面的程序,三次NSLog会输出什么?为什么?
NSMutableArray* ary = [[NSMutableArrayarray]retain]; NSString*str = [NSStringstringWithFormat:@"test"];// 1 [strretain];// 2 [aryaddObject:str];// 3 NSLog(@"%d", [strretainCount]); [strretain];// 4[strrelease];// 3 [strrelease];// 2 NSLog(@"%d", [strretainCount]); [aryremoveAllObjects];// 1 NSLog(@"%d", [str retainCount]);
结果:3、2、1
10、OC中创建线程的方法是什么?如果指定在主线程中执行代码?如何延时执行代码?
创建线程的方法
NSThread
NSOperationQueue和NSOperation
GCD
主线程中执行代码
[self performSelectorOnMainThread: withObject: waitUntilDone:]; [self performSelector: onThread:[NSThread mainThread] withObject: waitUntilDone:]; dispatch_async(dispatch_get_main_queue(), ^{ });
延时执行
double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ }); [self performSelector: withObject: afterDelay:]; [NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:];
11、深拷贝和浅拷贝有什么区别?
浅拷贝:指针(地址)拷贝,不会产生新对象
深拷贝:内容拷贝,会产生新对象
12、分类有什么好处? 分类和继承有什么区别?
分类可以在不修改原来类模型的基础上拓充方法
分类只能扩充方法、不能扩充成员变量;继承可以扩充方法和成员变量
继承会产生新的类
13、分类和扩展有什么区别?
分类是有名称的,类扩展没有名称
分类只能扩充方法、不能扩充成员变量;类扩展可以扩充方法和成员变量
类扩展一般就写在.m文件中,用来扩充私有的方法和成员变量(属性)
14、OC中的协议和Java中的接口有什么不同?
Java的接口中声明的方法必须都实现
Oc的protocol中声明的方法并不一定要实现
15、什么是 KVO 和 KVC?
KVC是键值编码,可以通过一个字符串的key(属性名)修改对象的属性值
KVO是键值监听,可以监听一个对象属性值的改变
16、What is purpose of delegates?
两个对象之间传递数据和消息
解耦,拆分业务逻辑
17、OC中的mutable 和immutable分别指什么?
mutable是可变类型,比如NSMutableArray,可以动态往里面添加元素
immutable是不可变类型,比如NSArray,固定的存储空间,不能添加元素
18、为什么我们把OC称为运行时语言?
动态绑定:对象类型在运行时才真正确定
多态性
19、 NSNotification 和 protocol有什么不同?
通过NSNotification可以给多个对象传递数据和消息
通过protocol(代理模式)只能给一个对象传递数据和消息
20、什么是 push notification?
本地推送:程序内部弹出通知到用户设备
远程推送:由推送服务器推送通知到用户设备
21、NSRunLoop的实现机制,及在多线程中如何使用?
NSRunLoop是IOS消息机制的处理模式
1.NSRunLoop的主要作用:控制NSRunLoop里面线程的执行和休眠,在有事情做的时候使当前NSRunLoop控制的线程工作,没有事情做让当前NSRunLoop的控制的线程休眠。
2.NSRunLoop 就是一直在循环检测,从线程start到线程end,检测inputsource(如点击,双击等操作)同步事件,检测timesource同步事件,检测到输入源会执行处理函数,首先会产生通知,corefunction向线程添加runloop observers来监听事件,意在监听事件发生时来做处理。
3.runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers
使用
1. 只有在为你的程序创建次线程的时候,才需要运行run loop。对于程序的主线程而言,run loop是关键部分。Cocoa提供了运行主线程run loop的代码同时也会自动运行run loop。IOS程序UIApplication中的run方法在程序正常启动的时候就会启动run loop。如果你使用xcode提供的模板创建的程序,那你永远不需要自己去启动run loop
2. 在多线程中,你需要判断是否需要run loop。如果需要run loop,那么你要负责配置run loop并启动。你不需要在任何情况下都去启动run loop。比如,你使用线程去处理一个预先定义好的耗时极长的任务时,你就可以毋需启动run loop。Run loop只在你要和线程有交互时才需要
22、IOS7之前,后台执行内容有几种形式,都是什么?
一般的应用在进入后台的时候可以获取一定时间来运行相关任务,也就是说可以在后台运行一小段时间(10S左右)。
1. 后台播放音乐
2. 后台GPS跟踪
3. 后台voip支持
23、简单说一下APP的启动过程,从main文件开始说起。
程序启动分为两类:1.有storyboard 2.没有storyboard
有storyboard情况下:
1.main函数
2.UIApplicationMain
* 创建UIApplication对象
* 创建UIApplication的delegate对象
3.根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
* 创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口
没有storyboard情况下:
1.main函数
2.UIApplicationMain
* 创建UIApplication对象
* 创建UIApplication的delegate对象
3.delegate对象开始处理(监听)系统事件(没有storyboard)
* 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
* 在application:didFinishLaunchingWithOptions:中创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口
24、把程序自己关掉和程序进入后台,远程推送的区别?
1. 关掉后不执行任何代码,不能处理事件
2. 应用程序进入后台状态不久后转入挂起状态。在这种状态下,应用程序不执行任何代码,并有可能在任意时候从内存中删除。只有当用户再次运行此应用,应用才会从挂起状态唤醒,代码得以继续执行.或者进入后台时开启多任务状态,保留在内存中,这样就可以执行系统允许的动作
3. 远程推送是由远程服务器上的程序发送到APNS,再由APNS把消息推送至设备上的程序,当应用程序收到推送的消息会自动调用特定的方法执行事先写好的代码
25、本地通知和远程推送通知对基本概念和用法?
本地通知和远程推送通知都可以向不在前台运行的应用发送消息,这种消息既可能是即将发生的事件,也可能是服务器的新数据.不管是本地通知还是远程通知,他们在程序界面的显示效果相同,都可能显示为一段警告信息或应用程序图标上的微章.
本地通知和远程推送通知的基本目的都是让应用程序能够通知用户某些事情, 而且不需要应用程序在前台运行.二者的区别在于本地通知由本应用负责调用,只能从当前设备上的iOS发出, 而远程通知由远程服务器上的程序发送到APNS,再由APNS把消息推送至设备上的程序
26、 UITableViewController中,创建UITableViewCell时,initWithSytle:resuseIdentifier中,reuseIdentifier有什么用?简述UITableViewCell的复用原理.
复用队列的元素增加:只有在cell被滑动出界面的时候,此cell才会被加入到复用队列中。每次在创建cell的时候,程序会首先通过调用dequeueReusableCellWithIdentifier:cellType方法,到复用队列中去寻找标示符为“cellType”的cell,如果找不到,返回nil,然后程序去通过调用[[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease]来创建标示符为“cellType”的cell。
27、 ViewController的loadView, viewDidLoad, viewDidUnload分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?
答:viewDidLoad在view 从nib文件初始化时调用,loadView在controller的view为nil时调用。此方法在编程实现view时调用,view 控制器默认会注册memory warning notification,当view controller的任何view 没有用的时候,viewDidUnload会被调用,在这里实现将retain 的view release,如果是retain的IBOutlet view 属性则不要在这里release,IBOutlet会负责release 。
28、Objective C中的selector是什么?
你可以理解 @selector()就是取类方法的编号,他的行为基本可以等同C语言的中函数指针,只不过C语言中,可以把函数名直接赋给一个函数指针,而Objective-C的类不能直接应用函数指针,这样只能做一个@selector语法来取.它的结果是一个SEL类型。这个类型本质是类方法的编号(函数地址)。
29、定义属性时,什么情况使用copy,assign,和retain?
assign用于简单数据类型,如NSInteger,double,bool,retain 和copy用户对象,copy用于当 a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,a和b各自有自己的内存,就可以解决这个问题。retain 会使计数器加一,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
if (property != newValue) { [property release]; property = [newValue retain]; }
30、单件实例是什么?
Foundation 和 Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。举例来说,NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配 和初始化。 单件对象充当控制中心的角色,负责指引或协调类的各种服务。如果类在概念上只有一个实例(比如NSWorkspace),就应该产生 一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您可以使用单件实例机制,而不是工厂方法或函数。