iOS_收藏

iOS知识点(一)

2015-12-30  本文已影响192人  Nidalee丶

1. 什么是arc?(arc是为了解决什么问题诞生的?)

相关知识:
1.与ARC相对的是MRC, 手动引用计数, 可以简称MRC (Manual Reference Counting) 所有对象的内容都需要我们手动管理, 需要程序员自己编写release/retain等代码
2.ARC的判断原则:只要没有强指针指向对象,对象就会被释放。
(1)强指针:默认的情况下,所有的指针都是强指针,关键字strong
(2)弱指针:_ _weak关键字修饰的指针
3.ARC的特点总结:
(1)不允许调用release,retain,retainCount
(2)允许重写dealloc,但是不允许调用[super dealloc]
(3)@property的参数:
Strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针
Weak:相当于原来的assign,(适用于oc对象类型),成员变量是弱指针
Assign:适用于非OC对象类型(基础类型)

2. 请解释以下keywords的区别: assign vs weak, __block vs__weak

相关知识
在垃圾回收机制里面,如果你同时使用__weak__block来标识一个变量,那么该block将不会保证它是一直是有效的。 如果你在实现方法的时候使用了block,对象的内存管理规则更微妙:也是(__weak__block区别:)
(1)如果你通过引用来访问一个实例变量,self会被retain。
(2)如果你通过值来访问一个实例变量,那么变量会被retain

扩展:NSTimer注意避免循环引用的地方,需要找个合适的时机和地方来 invalidate timer
在引用计数的环境里面,默认情况下当你在block里面引用一个Objective-C对象的时候,该对象会被retain。当你简单的引用了一个对象的实例变量时,它同样被retain。但是被__block存储类型修饰符标记的对象变量不会被retain

3. __block在arc和非arc下含义一样吗?

//非ARC
__block typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt){ 
//使用weakSelf访问self成员
 [weakSelf anotherFunc];
};

4. 使用atomic一定是线程安全的吗?

atomic有个很大的问题是很慢,要比nonatomic慢20倍。
当然最后建议这种数值数值变化可以让服务器来做

5. 描述一个你遇到过的retaincycle例子。

一个下拉刷新,那个view和vc互相强引用,导致了没释放。view回去调用vc的scrollview的contentoffset

6. +(void)load; +(void)initialize;有什么用处?

举个例子:
由于 load 方法会在类被 import 时调用一次, 而这时往往是改变类的行为的最佳时机. 我在 DKNightVersion 中使用 method swizlling 来修改原有的方法时, 就是在分类 load 中实现的.

我在实际的项目中并没有遇到过必须使用这个方法的情况, 在该方法中主要做 静态变量的设置 并用于 确保在实例初始化前某些条件必须满足 .

7. 为什么其他语言里叫函数调用,objective-c语言里则是给对象发消息(或者谈下对runtime的理解)

**然而 Objective-C(ObjC) 是一门动态的语言, 整个 ObjC 语言都是尽可能的将所有的工作推迟到运行时才决定. 它基于 runtime 来工作, runtime 就是 ObjC 的灵魂, 其核心就是消息发送 objc_msgSend **

我们几乎可以使用 runtime 修改 Objective-C 中的一切:
*class property object ivar method protocol *

8. 什么是methodswizzling?

在DKNigtVersion (为iOS应用添加夜间模式) 中能够看到大量 method swizzling 的使用, 方法的调用时机就是在上面提到的 load 方法中, 不在 initialize 方法中改变方法实现的原因是 initialize 可能会被子类所继承并重新执行最终导致错误 , 而 load 并不会被继承并重新执行.

9. UIView和CALayer是啥关系?

在 iOS 上 当你处理一个一个有一个的 UIView 时实际上是在操作 CALayer . 尽管有的时候你并不知道 (直接操作 CALayer 并不会在对效率有着显著的提升).

1.你可以通过操作 UIView 在一个更高的层级上处理与用户的交互, 触摸, 点击, 拖拽等事件, 这些都是在 UIKit 这个层级上完成的.
2.UIView 和 NSView(AppKit) 的实现极其不同, 而使用 Core Animation 可以实现底层代码地重用, 因为在 Mac 和 iOS 平台上都使用着近乎相同的 Core Animation 代码, 这样我们可以对这个层级进行抽象在两种平台上产生 UIKit 和 AppKit 用于不同平台的框架.
3.使用 CALayer 的唯一原因大概是便于移植到不同的平台, 如果仅仅使用 Core Animation 层级, 处理用户的交互时间需要写更多的代码.

10. 如何高性能的给UIImageView加个圆角?
(不准说layer.cornerRadius!)

<贝塞尔曲线> 可以完美解决

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];  
imageView.center = CGPointMake(200, 300);  
UIImage *anotherImage = [UIImage imageNamed:@"image"];  
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);  
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
  cornerRadius:50] addClip];
[anotherImage drawInRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();  
[self.view addSubview:imageView];

11. 使用drawRect有什么影响?(这个可深可浅,你至少得用过。。)

12. ASIHttpRequest或者SDWebImage里面给
UIImageView加载图片的逻辑是什么样的?(把
UIImageView放到UITableViewCell里面问更赞)

首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以 url 作为数据的索引先在内存中寻找是否有对应的缓存, 如果缓存未命中就会在磁盘中利用 MD5 处理过的 key 来继续查询对应的数据, 如果找到了, 就会把磁盘中的缓存备份到内存中.

然而, 假设我们在内存和磁盘缓存中都没有命中, 那么manager就会调用 SDWebImageDownloader 对象的方法downloadImageWithURL:...来下载图片, 过程中调用另一个方法:
addProgressCallback:andCompletedBlock:fotURL:createCallback:来存储下载过程中和下载完成的回调, 当回调块是第一次添加的时候, 方法会实例化一个 NSMutableURLRequest 和 SDWebImageDownloaderOperation , 并将后者加入 downloader 持有的下载队列开始图片的异步下载.

13. 麻烦你设计个简单的图片内存缓存器(移除策略是一定要说的)

图片的内存缓存,可以考虑将图片数据保存到一个数据模型中。所以在程序运行时这个模型都存在内存中。
移除策略:释放数据模型对象。

14. 讲讲你用Instrument优化动画性能的经历吧(别问我什么是Instrument)

考虑程序的性能,可以借助数据化图形化的输出方式。与其花费时间在优化小细节上不如多点时间找到你改优化的地方.时间事件查看器 ——> Time Profiler打开Instrument的步骤:xcode ——> open developer Tool ——> instrument 选取相应的strumnet的工具,选择相应的strument里面的工具,然后选择模拟器或者真机上面的应用,点击右上角的开始按钮,然后就可以看到相应内容

Instrument详细介绍

15. loadView是干嘛用的?

loadView默认做的事情是:如果此ViewController存在一个对应的nib文件,那么就加载这个nib。否则,就创建一个UIView对象。
如果你用Interface Builder来创建界面,那么不应该重载这个方法。
如果你想自己创建view对象,那么可以重载这个方法。此时你需要自己给view属性赋值。你自定义的方法不应该调用super。如果你需要对view做一些其他的定制操作,在viewDidLoad里面去做。

1、如果你用了nib文件,重载这个方法就没有太大意义。因为loadView的作用就是加载nib。如果你重载了这个方法不调用super,那么nib文件就不会被加载。如果调用了super,那么view已经加载完了,你需要做的其他事情在viewDidLoad里面做更合适。
2、如果你没有用nib,这个方法默认就是创建一个空的view对象。如果你想自己控制view对象的创建,例如创建一个特殊尺寸的view,那么可以重载这个方法,自己创建一个UIView对象,然后指定 self.view = myView; 但这种情况也没有必要调用super,因为反正你也不需要在super方法里面创建的view对象。如果调用了super,那么就是浪费了一些资源而已

16. viewWillLayoutSubView你总是知道的。

横竖屏切换的时候,系统会响应一些函数,其中
viewWillLayoutSubviews 和 viewDidLayoutSubviews。

- (void)viewWillLayoutSubviews  {   
   [self _shouldRotateToOrientation:(UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation];  
}  
-(void)_shouldRotateToOrientation:(UIDeviceOrientation)orientation {  
   if (orientation == UIDeviceOrientationPortrait ||orientation ==UIDeviceOrientationPortraitUpsideDown) {
// 竖屏 }
 else {
// 横屏     } 
}
- (NSUInteger)supportedInterfaceOrientations{
    // 切换横屏
    return UIInterfaceOrientationMaskLandscape;
}

通过上述一个函数就知道横竖屏切换的接口了。
注意:viewWillLayoutSubviews只能用在ViewController里面,在view里面没有响应。

17. GCD里面有哪几种Queue?你自己建立过串行queue吗?背后的线程模型是什么样的?

18. 用过coredata或者sqlite吗?读写是分线程的吗?遇到过死锁没?咋解决的?

19. http的post和get啥区别?(区别挺多的,麻烦多说点)

GET和POST与数据如何传递没有关系, GET和POST是由HTTP协议定义的。在HTTP协议中,Method和Data(URL, Body, Header)是正交的两个概念,也就是说,使用哪个Method与应用层的数据如何传输是没有相互关系的。HTTP没有要求,如果Method是POST数据就要放在BODY中。也没有要求,如果Method是GET,数据(参数)就一定要放在URL中而不能放在BODY中.

(1).首先是”GET方式提交的数据是有字节限制的”,因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了。其限制取决于操作系统的支持。
  注意这是限制是整个URL长度,而不仅仅是你的参数值数据长度。
 (2).理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

20. 我知道你大学毕业过后就没接触过算法数据结构了,但是请你一定告诉我什么是Binary search tree? search的时间复杂度是多少?我很想知道!

可以看到,二叉搜索树的dictionary operation的时间复杂度与树的高度h相关。所以需要尽可能的降低树的高度,由此引出平衡二叉树Balanced binary tree。它要求左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这样就可以将搜索树的高度尽量减小。常用算法有红黑树、AVL、Treap、伸展树等。

上一篇 下一篇

猜你喜欢

热点阅读