美文网首页
iOS面试题汇总(基础篇一)

iOS面试题汇总(基础篇一)

作者: __Gavin__ | 来源:发表于2018-05-14 16:06 被阅读0次
1. 比较以下关键词的区别:strong, weak, assign, copy

strong:修饰的对象引用计数会增加1,该对象只要引用计数不为0则不会被销毁,所以将其设为nil引用计数归0可以销毁它。
weak:仅指向对象,其修饰的对象引用计数不会增加。该对象引用计数归0时会自行在内存中销毁。
assign:主要用于修饰基本数据类型,如NSInteger和CGFloat,这些数值主要存在于栈上。
weak与assign区别: weak一般用来修饰对象,assign一般用来修饰基本数据类型。原因是assign修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而基本数据类型在栈上,系统会自动处理其上内存,不会造成野指针。
copy:copy的复制每次会在内存中拷贝一份对象,指针指向拷贝得来对象的地址,不对原对象造成影响且无关系。一般用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary。
:Objective-C 中,基本数据类型的默认关键字是atomic, readwrite, assign;普通属性的默认关键字是atomic, readwrite, strong。基本数据类型主要存在于栈上,对象存在于堆上。

2. 比较以下关键词的区别:__weak,__block

__weak:与weak基本相同,前者用于修饰变量(variable),后者用于修饰属性(property)。__weak 主要用于防止block中的循环引用。
__block:同样用于修饰变量,它是引用修饰,所以其修饰的值是动态变化的,即可以被重新赋值的。__block用于修饰某些block内部将要修改的外部变量。
:__weak和__block的使用场景几乎与block息息相关。而所谓block,就是Objective-C对于闭包的实现。闭包就是没有名字的函数,或者理解为指向函数的指针。

3. 比较以下关键词的区别:atomatic, nonatomic

atomic:修饰的对象会保证setter和getter的完整性,任何线程对其访问都可以得到一个完整的初始化后的对象。因为要保证操作完成,所以速度慢。它比nonatomic安全,但也并不是绝对的线程安全,例如多个线程同时调用set和get就会导致获得的对象值不一样。绝对的线程安全就要用关键词synchronized。
nonatomic:修饰的对象不保证setter和getter的完整性,所以多个线程对它进行访问,它可能会返回未初始化的对象。正因为如此,它比atomic快,但也是线程不安全的。

4. 找出下面代码错误
UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectMake(100,100,100,100)];
alertLabel.text = @"Wait 4 seconds...";
[self.view addSubview:alertLabel];

NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperationWithBlock:^{
     [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:4]];
     alertLabel.text = @"Ready to go!";
}];

所有UI的相关操作应该在主线程进行,正确代码入下:

UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectMake(100,100,100,100)];
alertLabel.text = @"Wait 4 seconds...";
[self.view addSubview:alertLabel];
    
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperationWithBlock:^{
     [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:4]];
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{
          alertLabel.text = @"Ready to go!";
     }];
}];
5. 以scheduledTimerWithTimeInterval的方式触发的timer,在滑动页面上的列表时,timer会暂停,为什么?该如何解决?

原因:在于滑动时当前线程的runloop切换了mode用于列表滑动,导致timer暂停。
runloop中的mode主要用来指定事件在runloop中的优先级,有以下几种:

  • Default(NSDefaultRunLoopMode):默认,一般情况下使用;
  • Connection(NSConnectionReplyMode):一般系统用来处理NSConnection相关事件,开发者一般用不到;
  • Modal(NSModalPanelRunLoopMode):处理modal panels事件;
  • Event Tracking(NSEventTrackingRunLoopMode):用于处理拖拽和用户交互的模式。
  • Common(NSRunloopCommonModes):模式合集。默认包括Default,Modal,Event Tracking三大模式,可以处理几乎所有事件。

回到题中的情境。滑动列表时,runloop的mode由原来的Default模式切换到了Event Tracking模式,timer原来好好的运行在Default模式中,被关闭后自然就停止工作了。

解决方法:其一是将timer加入到NSRunloopCommonModes中。其二是将timer放到另一个线程中,然后开启另一个线程的runloop,这样可以保证与主线程互不干扰,而现在主线程正在处理页面滑动。示例代码如下:

// 方法1
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

// 方法2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:nil repeats:true];
    [[NSRunLoop currentRunLoop] run];
});
6. 写一条sql语句,查询出所在省以“湖”开头,邮编为“436001”的城市?

SELECT * FROM t_citys WHERE postcode = '%@' AND province LIKE '湖%%'

7. 用预处理指令#define声明一个常数,用以表明1年中有多少秒?(忽略闰年问题)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL, UL(表示无符号长整型)

8. 写一个宏MIN ,实现输入两个参数并返回较小的一个的功能

#define MIN(A,B) ((A) <= (B) ? (A) : (B)),不需要用if else
副作用:least = MIN(*p++, b); 此时转化如下:((*p++) <= (b) ? (*p++) :(b)),*p++会影响返回值的准确性。

9. static的作用
  • 函数体内static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
  • 在模块内的static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
  • 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
  • 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
  • 在类中的static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
10. 简述内存分区情况
  • 代码区:存放函数二进制代码。
  • 数据区:系统运行时申请内存并初始化,系统退出时由系统释放。 存放全局变量、静态变量、常量。
  • 堆区:通过malloc等函数或new等操作符动态申请得到,需程序员手动申请和释放。
  • 栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数。
11. #include<filename>和#include”filename”有什么区别
  • #include<filename>:直接在库文件目录中搜索所包含的文件;
  • #include”filename”:在当前目录下搜索所包含的文件,如果没有的话再到库文件目录搜索。
12. 写出const char * p; char const * p; char * const p; const char * const p;的区别?
  • const char * p:定义一个指向字符常数的指针,p可变,*p不可变。
  • char const * p:同上。
  • char * const p:定义一个指向字符的指针常数,*p可变,p不可变。
  • const char * const p:定义一个指向字符常数的指针常数,*p、p均不可变。
13. UIView与CLayer有什么区别?
  • UIView 是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由 CoreAnimation 来实现的。它真正的绘图部分,是由一个 CALayer 类来管理。 UIView 本身更像是一个 CALayer 的管理器,访问它的跟绘图和跟坐标有关的属性。
  • UIView 有个重要属性 layer ,可以返回它的主 CALayer 实例。

相关文章

网友评论

      本文标题:iOS面试题汇总(基础篇一)

      本文链接:https://www.haomeiwen.com/subject/rbkezxtx.html