斐波那契数列(Fibonacci sequence)
func Fib() -> Int {
var prev = 0
var curr = 1
for _ in 1 ..< 100 {
var temp = curr
curr = prev + curr
prev = temp
}
return curr
}
nil、Nil、NULL、NSNull的区别
nil:指向一个对象的空指针,对objective c id 对象赋空值.
Nil:指向一个类的空指针,表示对类进行赋空值.
NULL:指向其他类型(如:基本类型、C类型)的空指针, 用于对非对象指针赋空值.
NSNull:在集合对象中,表示空值的对象.
网络图片处理
SDWebImage的使用
第一步,下载SDWebImage,导入工程。github托管地址https://github.com/rs/SDWebImage
第二步,在需要的地方导入头文件
1 #import "UIImageView+WebCache.h"
第三步,调用sd_setImageWithURL:方法缓存图片,注意,这就是新版本的新方法,旧方法是setImageWithURL:。下面将几个方法都介绍一下。
1. sd_setImageWithURL:
/图片缓存的基本代码,就是这么简单
[self.image1 sd_setImageWithURL:imagePath1];
2. sd_setImageWithURL: completed:
//用block 可以在图片加载完成之后做些事情
[self.image2 sd_setImageWithURL:imagePath2 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"这里可以在图片加载完成之后做些事情");
}];
3. sd_setImageWithURL: placeholderImage:
//给一张默认图片,先使用默认图片,当图片加载完成后再替换
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"]];
4. sd_setImageWithURL: placeholderImage: completed:
//使用默认图片,而且用block 在完成后做一些事情
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"图片加载完成后做的事情");
}];
5. sd_setImageWithURL: placeholderImage: options:
//options 选择方式
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"] options:SDWebImageRetryFailed];
其他就不一一介绍了,oc是自文档语言,看方法名就知道干什么的了。除了带options选项的方法,其他的方法都是综合存储,也就是内存缓存和磁盘缓存结合的方式,如果你只需要内存缓存,那么在options这里选择SDWebImageCacheMemoryOnly就可以了。
如果不想深入了解,到这里你已经可以用SDWebimage进行图片缓存了,接下来我要解释options的所有选项,以及SDWebImage内部执行流程。
一、options所有选项:
//失败后重试
SDWebImageRetryFailed = 1 << 0,
//UI交互期间开始下载,导致延迟下载比如UIScrollView减速。
SDWebImageLowPriority = 1 << 1,
//只进行内存缓存
SDWebImageCacheMemoryOnly = 1 << 2,
//这个标志可以渐进式下载,显示的图像是逐步在下载
SDWebImageProgressiveDownload = 1 << 3,
//刷新缓存
SDWebImageRefreshCached = 1 << 4,
//后台下载
SDWebImageContinueInBackground = 1 << 5,
//NSMutableURLRequest.HTTPShouldHandleCookies = YES;
SDWebImageHandleCookies = 1 << 6,
//允许使用无效的SSL证书
//SDWebImageAllowInvalidSSLCertificates = 1 << 7,
//优先下载
SDWebImageHighPriority = 1 << 8,
//延迟占位符
SDWebImageDelayPlaceholder = 1 << 9,
//改变动画形象
SDWebImageTransformAnimatedImage = 1 << 10,
SDWebImage内部实现过程
1. 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
2. 进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
3. 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
4. SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
5. 如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
6. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
7. 如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
8. 如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
9. 共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
10. 图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
11. connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
12. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
13. 图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
14. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
15. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
16. 通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
17. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
18. SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
19. SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
20. SDWebImagePrefetcher 可以预先下载图片,方便后续使用。
从上面流程可以看出,当你调用setImageWithURL:方法的时候,他会自动去给你干这么多事,当你需要在某一具体时刻做事情的时候,你可以覆盖这些方法。比如在下载某个图片的过程中要响应一个事件,就覆盖这个方法:
//覆盖方法,指哪打哪,这个方法是下载imagePath2的时候响应
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"显示当前进度");
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
NSLog(@"下载完成");
}];
对于初级来说,用sd_setImageWithURL:的若干个方法就可以实现很好的图片缓存。
http://www.cocoachina.com/ios/20141212/10622.html
属性相关的关键字,可以按照一些功能来分类
线程相关
atomic:默认为该属性,功能为在多线程的情况下,编译器自动生成相应的线程安全代码,达到互斥加锁的目的,避免所对应的变量出现读写不同步的问题。
nonatomic:当该变量不需要考虑多线程的情况时使用该关键字,能够提高性能和效率。
atomic主要用于线程保护的,可以避免当一个线程在对一个地址进行访问时防止另一个线程对此地址同时进行访问,防止了数据错误。众所周知,线程锁会耗费系统资源,所以在实际使用时,如果没有线程相关的内容,建议使用nonatomic。
目前大部分的iOS app中,nonatomic的普遍使用也是基于性能考虑的。
读写相关
readwrite:默认类型,会自动生成相应的读写方法。
readonly:只生成相应的get方法,不生成set方法。
主要使用目的:控制外部类对该属性的访问权限。
内存引用相关
这里又根据系统版本分为两类,一类是iOS 5.0之前,一类是iOS 5.0加入了ARC机制之后。
ARC之前
assgin:默认类型,set方法中为直接赋值,即直接指向了一个地址,没有任何引用计数的更改。
retain:set方法中,首先释放(release)之前的对象,即去除对于旧对象的引用计数,并直接指向新的对象的地址,并使新对象的引用计数加一。
copy:set方法中,与retain类似,先release旧对象,然后对于新的对象进行copy,实质为使用新的内存空间和地址,引用计数唯一,并将目标对象的内容拷贝过来。可以认为是内容拷贝。
ARC之后
weak:弱引用,与assgin类似,只是当对象释放后,weak类型会自动置空,即将指针设为nil,避免野指针。
strong:强引用,默认类型,与retain类似。
内存计数方面的关键字是objc主要内容。
CALayer和UIView的区别联系
1 UIView是UIKIt的只能在iOS使用, CALayer是QuartzCore的 iOS和mac os通用
2 CALayer比UIView更加轻量级,但是可以实现同样的效果
3 UIView的CALayer类似UIView的子View树形结构
4 UIView比CALayer多了一个事件处理功能,也就是说UIView能处理用户触摸
5 UIView有个重要的属性layer,可以返回它的主CALayer实例.CALayer *layer = myView.layer
6 坐标系统: CALayer的坐标系统比UIView多了一个anchorPoint属性
8 渲染 当更新层 改变不能立即显示在屏幕上.当所有的层都准备好时,可以调用setNeedsDisplay方法来重绘显示.
9 变换 要在一个层中添加一个3D或仿射变换,可以分别设置层的transform或者affineTransform属性
10 变形Quartz Core的渲染能力 使二维图像可以被自由的操纵,就像是三维的.图像可以在一个三维坐标系中以任意的角度被旋转 缩放 和倾斜.CATransform3D的一套方法提供了一些魔术般的效果
简述同步和异步
同步:串行的执行任务 异步:并行的执行任务.同步函数不具备开启线程的能力,而异步函数具备
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就得到返回值了.也就是 由调用者主动等待这个调用结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果.换句话说就是当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用.
多线程安全怎么控制?
用互斥锁,队列组,栅栏函数,依赖
什么时候使用继承,什么时候使用类别
在OC中,一个类继承另一个类,就是继承了父类所有的属性和方法,并且可以扩充自己的属性:而类别是在不改变原有类的基础上进行方法扩充;
因此,根据开发需求,如果这个类需要扩充属性,或者需要重写系统的类的某些方法,用继承;如果只是对一个类扩充接口和模块,使用类别更加方便.
关键字const有什么含意?修饰类呢?static的作用,用于类呢?还有extern c的作用?
当使用 const修饰基数数据类型变量时,该变量就变为常量,进入静态区
当使用const修饰指针类型变量时:
当使用const在指针类型两边,那么该指针变量指向的内存空间的内容就不能改变了,但指针的指向可以改变.
如果const在变量的左边,那么该指针的指向不能改变了,而指向内存空间的内容可以改变
当使用const修饰符时,const NSSting *str,相当于修饰该对象,表示对象是不可更改的.
static修饰变量,表示这个内部全局变量,只能在本文件中访问.系统会将该变量放进静态区,它的生命周期被延长到了程序结束
static修饰类, 表示这个内部的方法, 只能在本文件中访问.
extern c表示声明了一外部变量, 多个外部变量如果同名,实际指向的是同一块存储空间.
UIView从出现到销毁的过程?
loadView
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidlayoutSubviews
viewDidAppear
viewWillDisappear
viewDidDisappear
frame和bounds有什么不同
frame的位置是相对父空间的左上角来说的 参照的是父类的坐标系,指的是空间在父控件内的位置和大小
bounds的位置是相对控件自身的左上角来说的,参照的是自身坐标系,指的是自己本身的大小
NSTimer和GCD的定时器有什么区别
NSTimer 可以调用invalidate进行撤销,创建和撤销必须在同一线程
NSTimer需要交定时器添加到当前的runloop中
它的时间单位是秒
GCD一旦执行就不能撤销
GCD中的定时器不受runloop模式的影响
时间单位是纳秒
应用程序的沙盒下,都有哪些文件夹?它们有什么特点?本地缓存一般存在哪个文件下?
1 Documents
将应用程序的数据文件保存在该目录下.不过这些数据类型仅限于不可以再生的数据,可再生的数据文件应该存在LIbrary/Cache下
2 Library 它有两个子文件
caches 主要是缓存文件,用户使用过程中缓存都可以保存在这些目录中.保存那些可再生的文件,比如网络数据请求.因此,应用程序通常还需要负责删除这些文件.
Preferences 应用程序的偏好设置文件. 我们使用NSUserDefaults写的设置数据都会保存到该目录下的一个plist文件中 它会被iTunes同步
3. tmp
各种临时文件, 保存应用再次启动时不需要的文件.而且,当应用不在需要这些文件时应主动将其删除,因为该目录下的东西随时有可能被系统清除,目前已知的一种可能清理的原因是系统磁盘存储空间不足的时候
__weak什么时候用?
当两个对象互相引用的时候,一端用strong,另一端必须用weak .例如: A拥有B, B也拥有A, 那么必须一方使用weak
一般UI控件都可以使用weak,因为自身已经对它进行一次强引用,没有必要再强引用一次.
Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?
Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++的多重继承;Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。
写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name
- (void) setName:(NSString*) str
{
[str retain];
[name release];
name = str;
}
- (void)setName:(NSString *)str
{
id t = [str copy];
[name release];
name = t;
}
Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:
类别的作用?继承和类别在实现中有何区别?
category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改,并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用1).将类的实现分散到多个不同文件或多个不同框架中。2).创建对私有方法的前向引用。3).向对象添加非正式协议。继承可以增加,修改或者删除方法,并且可以增加属性。
什么是KVO和KVC?
VC:键 – 值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制。
KVO:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码 比如我自定义的一个button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。
对于kvc机制如何通过key寻找到value:
“当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。这样做有很多好处,下面的两个例子说明了这样做的好处。“
对于单例的理解
在objective-c中要实现一个单例类,至少需要做以下四个步骤:
1).为单例对象实现一个静态实例,并初始化,然后设置成nil,
2).实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,
3).重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,
4).适当实现allocWitheZone,copyWithZone,release和autorelease。
并行(Concurrent) & 串行(Serial)
并行和串行描述的是任务和任务之间的执行方式,并行是任务A和任务B可以同时执行,串行是任务A执行完了任务B才能执行(按顺序执行)。
异步(Asynchronous) & 同步(Synchronous)
异步和同步描述的其实就是函数什么时候返回. 比如用来下载图片的函数: 同步函数只有在image下载结束之后才返回, 下载的这段时间函数只能等待,而异步函数,不会去等它完成(异步函数不会堵塞当前线程去执行下一个函数)。
并发(Concurrency) & 并行(Parallelism)
这个更容易混淆了, 并发和并行都是用来让不同的任务可以"同时执行"。 只是并行是真同时,而并发是假同时(是CPU地在各个进程之间快速切换, 给人一种能同时处理多任务的错觉)。
CAAnimation继承结构