1.定义协议时,在协议名称后面加上的作用是:A、B、C
A.新定义的协议遵守
B.新定义的协议是
C.遵守新定义的协议的对象,也必须遵守
D.遵守新定义的协议的对象,必须是 NBObject 的子类
解析:如果一个协议继承于另外一个协议,声明方法为尖括号里面填入父协议名称。
@protocol SonProtocol@end
既然代表是继承关系,那么A、B、C都符合
2.以下代码存在的问题是:C
dispatch_queue_t queue = dispatch_queue_create("com.apple.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(actionTime:) userInfo:nil repeats:YES];
});
- (void)actionTime:(NSTimer *)time {
NSLog(@"------ %@",[NSDate date]);
}
A.运行时崩溃
B.死锁
C.定时器不执行
D.定时器只执行一次
解析:首先看 DISPATCH_QUEUE_CONCURRENT 并发队列 和 dispatch_async 异步执行,应该不会产生死锁问题
所以此处考察的是 NSTimer 的用法,确切说是 NSTimer 在子线程中的应用
主线程的 RunLoop 是默认开启的,但是在子线程中需要手动启动 RunLoop 对象才能进入运行循环,从而发挥定时器的作用
代码修改如下可以正常运行:
dispatch_queue_t queue = dispatch_queue_create("com.apple.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(actionTime:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
// 这里需要注意不要使用[[NSRunLoop currentRunLoop] run],因为会无法终止这个 RunLoop
// 而且这里必须是 NSDefaultRunLoopMode,使用 NSRunLoopCommonModes 的话定时器不执行
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
});
- (void)actionTime:(NSTimer *)time {
NSLog(@"------ %@",[NSDate date]);
}
// 必要的时候使用 CFRunLoopStop(CFRunLoopGetCurrent()); 停止RunLoop
或者是改成这样:在主线程中设置定时器
dispatch_async(dispatch_get_main_queue(), ^{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(actionTime:) userInfo:nil repeats:YES];
});
- (void)actionTime:(NSTimer *)time {
NSLog(@"------ %@",[NSDate date]);
}
参考文章:如何正确的使用NSTimer
延伸阅读:iOS趣味篇:NSTimer到底准不准?
3.以下哪些情况容易造成循环引用:A、B、C、D
A. dispatch_async 的 block 中使用 self
B. 使用 strong 修饰的 delegate 属性
C. self 作为 NSNotificationCenter 的 observer
D. self 作为所持有的 NSTimer 的 target
延伸小测试:以下情景中有哪些会造成循环引用?
4.以下哪些类跟 UIView 有继承关系(直接、间接的父类或子类):A、D
A. UIControl
B. UIGestureRecognizer
C. CALayer
D. UIResponder
解析:
UIControl : UIView
UIGestureRecognizer : NSObject
CALayer : NSObject
UIResponder : NSObject
UIView : UIResponder
所以 UIControl : UIView : UIResponder 答案:A、D
UIGestureRecognizer、CALayer 是 UIView 的属性类,但不存在继承关系
5.以下关于 OC 消息机制说法不正确的是:B、F
A. OC 的实例对象的 isa 指针指向它的类对象,类对象的 isa 指针指向它的元类对象
B. OC 调用一个未实现的实例方法,我们可以在 NSObject 的 resolveClassMethod 中进行添加方法进行补救
C. OC 可以运用运行时特性向 Class 的对象中动态添加方法
D. OC 的实例方法是存放在相应实例对象的 methodList 中,静态方法存在相应类对象的 methodList 中
E. OC 可以运用运行时特性向对象的 Category 中实现动态绑定属性,达到 Category 添加成员变量的效果
F. OC 可以运用运行时特性通过 class_addIvar() 向编译好的 Class 添加成员变量
解析:A 正确,可以参考下方大图
解析:B 错误, resolveClassMethod 方法是针对类方法的决议,如果是实例方法,需要通过 resolveInstanceMethod,示例代码如下
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(test)) {
IMP imp = [self instanceMethodForSelector:@selector(myClassMethod)];
class_addMethod(self, sel, imp, "v@:");
return YES;
}
return YES;
}
- (void)myClassMethod {
NSLog(@"resolveInstanceMethod");
}
解析 E 正确,实现代码如下:
@interface UIImageView (test)
@property(nonatomic, strong) NSObject *style;
@end
@implementation UIImageView (test)
static char styleKey;
- (void) setStyle:(NSObject *) style
{
objc_setAssociatedObject(self, &styleKey, style, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSObject *) style
{
return objc_getAssociatedObject(self, &styleKey);
}
@end
解析 F 错误
不能向编译后得到的类中增加实例变量,只能向运行时创建的类中添加实例变量。
因为编译后的类已经注册在 runtime 中,类结构体中的 objc_ivar_list 实例变量的链表和instance_size 实例变量的内存大小已经确定,同时 runtime 会调用 class_setIvarLayout 或 class_setWeakIvarLayout 来处理 strong weak 引用。所以不能向存在的类中添加实例变量。
运行时创建的类是可以添加实例变量,调用 class_addIvar 函数。但是得在调用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上。
参考链接:resolveInstanceMethod和resolveClassMethod
参考链接:iOS开发-Runtime运行时特性详解
参考链接:iOS (Category)runtime动态添加属性
6.在HTTP请求中,返回代码401和500代表下列哪两种状态:B、C
A:请求网页不存在
B:未授权
C:服务器内部错误
D禁止访问
参考:http协议的状态码
7.以下代码输出的日志是:E
dispatch_sync(dispatch_get_main_queue(), ^{
printf("1");
});
printf("2");
A. 12
B. 21
C.1
D.2
E. 无输出
解析:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁;dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。
8.在开发过程中,block的使用很容易造成内存泄漏,对于下面代码会不会造成内存问题? 需要如何处理?:B
[UIView animateWithDuration:0.25 animations:^{
self.alpha = 0;
}];
A.会造成内存问题
B. 不会造成内存问题
会的话, 要如何处理_______
解析:此处block的使用不会造成循环引用,也不存在内存泄漏
9.以下代码第二行编译不通过,修改不正确的是:D
NSError * error = nil;
NSError ** plError = &error;
A. __strong NSError ** pError = &error;
B. NSError __strong ** pError = &error ;
C. NSError * __strong * pError = &error;
D. NSError ** __strong pError = &error;
解析:pError实例对象跟前一定有*修饰
10.runloop Observer 可以监听的事件为:A、D
A、进入runloop和退出runloop
B、执行完timer 事件
C、执行source事件之前和执行完source事件
D、等待前和唤醒后
解析:
kCFRunLoopEntry = (1UL << 0), 进入工作
kCFRunLoopBeforeTimers = (1UL << 1), 即将处理Timers事件
kCFRunLoopBeforeSources = (1UL << 2), 即将处理Source事件
kCFRunLoopBeforeWaiting = (1UL << 5), 即将休眠
kCFRunLoopAfterWaiting = (1UL << 6), 被唤醒
kCFRunLoopExit = (1UL << 7), 退出RunLoop
kCFRunLoopAllActivities = 0x0FFFFFFFU 监听所有事件