iOS 简单知识点总结
以下内容均来自网络,记下来以供自己学习
1. 比较GCD 和 NSOperation异同
相同点:GCD和NSOperation都是苹果提供的多线程实现方案。
不同点:GCD是轻量级的纯C写的多线程实现方案,使用起来非常方便,在开发中大量使用,但是对于取消和暂停线程就比较麻烦些。而NSOperation是面向对象的,兼容KVO,对于取消和暂停任务是非常容易的。
(GCD是基于c的底层api,NSOperation属于object-c类。
相对于GCD:
1.NSOperation拥有更多的函数可用,具体查看api。
2.在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。
3.有kvo,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)。
4.NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
gcd主要与block结合使用。
具体使用哪个,依需求而定。)
• GCD是基于C的底层API
• NSOperation属于object-c类。
• iOS首先引入的是NSOperation,IOS4之后引入了GCD和NSOperationQueue并且其内部是用GCD实现的。
NSOperation:
1 - NSOperation拥有更多的函数可用,具体查看API。
2 - 在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。
3 - 有KVO,可以监测operation是否
--------------------------正在执行isExecuted、
--------------------------是否结束isFinished、
--------------------------是否取消isCanceld;
4 - NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
NSOperationQueue的队列类型
• 主队列
o [NSOperationQueue mainQueue]
o 凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行
• 非主队列(其他队列)
o [[NSOperationQueue alloc] init]
o 同时包含了:串行、并发功能
o 添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行
GCD:
1 - 主要与block结合使用。代码简洁高效。
2 - GCD也可以实现复杂的多线程应用,主要是建立个个线程时间的依赖关系这类的情况,但是需要自己实现相比NSOperation要复杂。具体使用哪个,依需求而定。
GCD的队列类型
并发队列
- 全局
- 自己创建的
串行队列
- 主队列
- 自己创建的
从个人使用的感觉来看,比较合适的用法是:除了依赖关系尽量使用GCD,因为苹果专门为GCD做了性能上面的优化。
2 . UIViewController的生命周期方法有哪些 ?
当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序
- alloc 创建对象,分配空间
- init 初始化对象,初始化数据
- loadView 从nib载入视图 ,通常这一步不需要去干涉。
- viewDidLoad 载入完成,可以进行自定义数据以及动态创建其他控件
- viewWillAppear 视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了
- viewDidAppear 视图已在屏幕上渲染完成
当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反
- viewWillDisappear 视图将被从屏幕上移除之前执行
- viewDidDisappear 视图已经被从屏幕上移除,用户看不到这个视图了
3 . dealloc 视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放
关 于viewDidUnload :在发生内存警告的时候如果本视图不是当前屏幕上正在显示的视图的话, viewDidUnload将会被执行,本所有子视图将被销毁,以释放内存。 因此当这个视图再次显示在屏幕上的时候,viewDidLoad 再次被调用,以构造视图。
3 . 代理为什么使用weak
-
属性关系有两种主要类型:strong和weak,相当于非ARC环境里的retain和assign。只要存在一个强引用,对象就会一直存在,不会被销毁。
-
Objective-C中一直存在循环引用的问题,但在实际应用中很少出现循环引用。对于过去那些使用assign属性的地方,在ARC环境中要使用weak代替。大部分引用循环是由委托(delegate)引起的,所以应该总是把delegate属性声明为weak。当引用的对象被销毁之后,weak引用会被自动置为nil,与assign相比这是一个巨大的进步,因为assign可以指向被释放掉的内存,导致程序崩溃
assign 是直接赋值,而retain是引用引数加1;使用retain容易出现内存错误。
一个对象没必要管理自己delegate的生命周期,或者说没必要拥有该对象,所以只要知道它的指针就可以了,用指针找到对象去调用方法,也就是委托的实现。
或者换个角度,从内存管理方面也可以解释这个问题。delegate的生命周期不需要让该对象去控制,如果该对象对其使用retain很可能导致delegate所指向的对象无法正确的释放。
assign: 简单赋值,不更改索引计数
weak比assign多了一个功能,当对象消失后自动把指针变成nil
weak属性的变量是不为其所属对象持有的,并且在该变量被销毁之后,此weak变量的值会自动被赋值为nil。而assign属性一般是对C基本数据类型成员变量的声明,当然也可以用在对象类型成员变量上,只是其代表的意义只是单纯地拷贝所赋值变量的值。
4 . CALayer和UIView的关系
-
1 .首先UIView可以响应事件,Layer不可以:
UIView(UIWindow,UIApplication,UIViewController)继承于UIResponder,在UIResponder中系统定义处理各种事件和事件传递的接口(touchesBegan:withEvent),而CALayer直接继承于NSObject,并没有相应的处理事件接口 -
2 . View中frame getter方法,bounds和center,UIView并没有做什么工作;它只是简单的各自调用它底层的CALayer的frame,bounds和position方法(position:用来设置CALayer在父层中的位置以父层的左上角为原点(0, 0))
-
3 .
UIView主要是对显示内容的管理而 ,CALayer 主要侧重显示内容的绘制。
每个 UIView 内部都有一个 CALayer 在背后提供内容的绘制和显示,并且 UIView 的尺寸样式都由内部的 Layer 所提供。两者都有树状层级结构,layer 内部有 SubLayers,View 内部有 SubViews.但是 Layer 比 View 多了个AnchorPoint
在 View显示的时候,UIView 做为 Layer 的 CALayerDelegate,View 的显示内容由内部的 CALayer 的 display
CALayer 是默认修改属性支持隐式动画的,在给 UIView 的 Layer 做动画的时候,View 作为 Layer 的代理,Layer 通过 actionForLayer:forKey:向 View请求相应的 action(动画行为)
layer 内部维护着三分 layer tree,分别是 presentLayer Tree(动画树),modeLayer Tree(模型树), Render Tree (渲染树),在做 iOS动画的时候,我们修改动画的属性,在动画的其实是 Layer 的 presentLayer的属性值,而最终展示在界面上的其实是提供 View的modelLayer
两者最明显的区别是 View可以接受并处理事件,而 Layer 不可以
5 .imageNamed 和imageWithContentOfFile区别
- imageNamed是会把读取到的image存在某个缓存里面,第二次读取相同图片的话系统就会直接从那个缓存中获取,从某种意义上好像一种优化,但是imageNamed读取到的那个图片似乎不会因为Memory Warning而释放,所以用这个会导致在内存不足的时候闪退。简单的说imageNamed采用了缓存机制,如果缓存中已加载了图片,直接从缓存读就行了,每次就不用再去读文件了,效率会更高
使用imageNamed:加载图片
加载到内存中后,会一直停留在内存中,不会随着对象销毁而销毁
加载进图片后,占用的内存归系统管理,我们无法管理
相同的图片,图片不会重新加载
加载到内存中后,占据内存空间较大
使用 imageWithContentOfFile:加载图片
1 加载到内存中后,占据内存空间比较小
2 相同的图片会被重复加载到内存中
对象销毁的时候,加载到内存中得图片会被一起销毁
6 .常见的OC数据类型有哪些,和C基本数据类型有什么区别
object-c的数据类型有nsstring,nsnumber,nsarray,nsmutablearray,nsdata等等,这些都是class,创建后便是对象,而c语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;而object-c的nsnumber包含有父nsobject的方法和nsnumber自己的方法,可以完成复杂的操作。
而且OC还新增了一些数据类型:
基本数据类型:BOOL类型(只有两个取值真或者假)
指针类型:类(Class);id类型指针,NSObject *OC 中的对象类型,动态对象类型,万能指针----动态类型:就是指针的id类型.动态类型和静态类型相对, 像内置的明确的基本数据类型都属于静态类型(int,NSString等).静态类型在编译的时候就能被识别出来.所以若是程序发生了类型不对应,编译器就会发出警告. 而动态类型就编译器编译的时候是不能被识别的,要等到运行时(run time),即程序运行时才会根据语境来识别.所以这里面就有两个概念要分清:编译时和运行时.
Block类型:block类型,代码块数据类型
特殊类型:SEL,nil,选择器数据类型
7 . 什么时候使用delegate,什么时候使用notifaction
- Delegate是一种点对点的消息传送机制。传递给自己或者其他对象。有时候他还会返回一个影响事件如何被处理的值。
- Notification是一种一对多的消息传递方式。他的实质是广播信息给所有observer。消息发送者不需要知道谁是消息的接收者。他减少了对象之间的依赖。
- 优先使用delegate因为使用代理可以更好的理解controller之间的通信,增强代码可读性,使用通知中心:当你程序中的所有controller都需要知道一件事情
(代理:一般控件用的比较多,其实也可以用block实现,如果实现的接口比较多的话,建议用代理,如UITableview。
如果一个类能够获取到通知的对象,这种情况下,我们用代理的效率会更高,而且能够更好的实现对要代理的对象的管理。
通知:这东西是全局的,而且是同步的,如果你要全局发送消息,并且做的事情时间不长,不会阻塞线程的话,建议使用。
如果一个通知的发送者有多个接受者,而且接受的位置完全不确定,那么这种情况下用通知是比较好的方式
)
8 . 属性语义设置解释
1.readwrite表示读写设置中的可读可写(读写设置的默认值),编译器会为读写设 置声明为”readwrite”的属性自动合成setter和getter方法。
2.readonly表示读写设置中的只读,编译器会为读写设置声明为”readonly“的属性 自动合成”getter”方法,而不合成”setter“方法。
3 .assign是语义设置(语义设置的默认值),使用assign修饰的属性所对应的读写方 法中不会操作内存的引用计数,所以一般将不需要程序员管理的数据类型声明为 assign,如基本数据类型和结构体类型。
4 .retain是语义设置,使用retain修饰的属性所对应的读写方法中会对内存的引用计 数进行操作,以保证持有的对象不会被意外回收,OC中的对象使用retain修饰。
5 .copy是语义设置,使用copy修饰的属性所对应的读写方法中会将将要持有的对象 拷贝一份,并持有对象的副本而不是原对象。对于OC中的可变对象,使用copy修饰, 是”深拷贝“,在内存中生成一块新的内存空间,将原对象拷贝到新空间中;对于OC 中的不可变对象,使用copy修饰,是”浅拷贝“,只拷贝对象的内存地址。
6 .atomic:是原子特性(原子设置的默认值),在多线程环境下,使用atomic会保 证在同一时刻只有一条线程修改、访问对应的实例变量,保证了实例变量在多线程环 境下的安全性,但是比较耗费资源,所以只有对于需要线程安全的属性才使用atomic 来修饰。
7 .nonatomic:是原子特性,在多线程环境下不能保证线程安全,这种设置不会消 耗过多的资源,所以不需要保证多线程环境中线程安全的属性,声明为nonatomic。
8 .strong:ARC中的语义设置,相当于MRC中的retain,会操作内存的引用计数。
9 .week:ARC中的语义设置,相当于MRC中的assign,不仅不会操作内存的引用计 数,而且在对象被回收后,会将指针置为nil,防止”野指针“的出现。
9 .什么时候用NSMutableArray,什么时候用NSArray
NSArray是静态的数组,就是它所指向的内容是不可改变的,它指向一段内存区域,一旦初始化,不能通过它对该内存区域的数据进行修改操作,但是它可以读数据。
NSMutableArray是动态的是NSArray的子类,可以对所指向的内存区域内容进行更改,并可以增加数组内容
10 . NSNotification和KVO
两者都是观察者模式,不同的是,KVO是被观察者直接发送消息给观察者,是对象间的交互,而通知则是观察者和被观察者通过通知中心对象之间进行交互,即消息由被观察者发送到通知中心对象,再由中心对象发给观察者,两者之间并不进行直接的交互
代理和前两者的区别
代理只能一对一,一个对象只有一个代理,而KVO和通知可以一对多,一个通知可以发给多个观察者
KVO是一个对象能够观察另外一个对象的属性的值,并且能够发现值的变化。前面两种模式更加适合一个controller与任何其他的对象进行通信,而 KVO更加适合任何类型的对象侦听另外一个任意对象的改变(这里也可以是controller,但一般不是controller)。这是一个对象与另外一 个对象保持同步的一种方法,即当另外一种对象的状态发生改变时,观察对象马上作出反应。它只能用来对属性作出反应,而不会用来对方法或者动作作出反应。必须在dealloc方法当中移除观察者否则会崩溃
优点:
1.能够提供一种简单的方法实现两个对象间的同步。例如:model和view之间同步;
2.能够对非我们创建的对象,即内部对象的状态改变作出响应,而且不需要改变内部对象(SKD对象)的实现;
3.能够提供观察的属性的最新值以及先前值;
4.用key paths来观察属性,因此也可以观察嵌套对象;
5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察
缺点:
1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;
2.对属性重构将导致我们的观察代码不再可用
11 . NSTimer使用时注意事项
1:如果想要销毁timer,则必须先将timer置为失效,否则timer就一直占用内存而不会释放。造成逻辑上的内存泄漏。该泄漏不能用xcode及instruments测出来。
另外对于要求必须销毁timer的逻辑处理,未将timer置为失效,若每次都创建一次,则之前的不能得到释放,则会同时存在多个timer的实例在内存中。
*注意timer在不需要时,一定要调用invalidate方法使定时器失效,否则得不到释放- -(void)invalidate;
这个是唯一一个可以将计时器从runloop中移出的方法。
2: NSTime使用时,需要将timer加到runLoop中
12 . cocoa touch框架
Core Audio
Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。
Core Data
提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。
下面是 Cocoa Touch 中一小部分可用的框架:
音频和视频:
Core Audio
Media Library
AV Foundation
数据管理:
Core Data
SQLite
图形和动画:
Core Animation
OpenGL
Quartz 2D
网络:
WebKit
BSD Sockets
用户应用:
Address Book
Core Location
Map Kit
Store Kit
13 . 内存管理
内存管理准则:谁强引用过,谁就在不再使用时使引用计数减一
对于内存的使用和优化常见的有以下方面:
重用问题:如UITableViewCells、UICollectionViewCells、UITableViewHeaderFooterViews设置正确的reuseIdentifier,充分重用。
尽量把views设置为不透明:当opque为NO的时候,图层的半透明取决于图片和其本身合成的图层为结果,可提高性能。
不要使用太复杂的XIB/Storyboard:载入时就会将XIB/storyboard需要的所有资源,包括图片全部载入内存,即使未来很久才会使用。那些相比纯代码写的延迟加载,性能及内存就差了很多。
选择正确的数据结构:学会选择对业务场景最合适的数组结构是写出高效代码的基础。比如,数组: 有序的一组值。使用索引来查询很快,使用值查询很慢,插入/删除很慢。字典: 存储键值对,用键来查找比较快。集合: 无序的一组值,用值来查找很快,插入/删除很快。
gzip/zip压缩:当从服务端下载相关附件时,可以通过gzip/zip压缩后再下载,使得内存更小,下载速度也更快。
延迟加载:对于不应该使用的数据,使用延迟加载方式。对于不需要马上显示的视图,使用延迟加载方式。比如,网络请求失败时显示的提示界面,可能一直都不会使用到,因此应该使用延迟加载。
数据缓存:对于cell的行高要缓存起来,使得reload数据时,效率也极高。而对于那些网络数据,不需要每次都请求的,应该缓存起来,可以写入数据库,也可以通过plist文件存储。
处理内存警告:一般在基类统一处理内存警告,将相关不用资源立即释放掉
重用大开销对象:一些objects的初始化很慢,比如NSDateFormatter和NSCalendar,但又不可避免地需要使用它们。通常是作为属性存储起来,防止反复创建。
避免反复处理数据:许多应用需要从服务器加载功能所需的常为JSON或者XML格式的数据。在服务器端和客户端使用相同的数据结构很重要。
使用Autorelease Pool:在某些循环创建临时变量处理数据时,自动释放池以保证能及时释放内存。
正确选择图片加载方式:详情阅读细读UIImage加载方式
14:项目目录结构:
一个合理的目录结构首先应该是清晰的,让人一眼看上去就能大概了解目录的职责,且容易应对新的变化。
目录结构
AppDelegate 这个目录下放的是AppDelegate.h(.m)文件,是整个应用的入口文件,单独拿出来。
Models 这个目录下放一些与数据相关的Model文件
BaseModel.h BaseModel.m…….
View(视图):
Controller(控制器):
Expand(拓展):放一些工具类(Tool),宏,网络(Network),分类(Category),数据库(DataBase)等
Resource(资源):plist文件或者图片之类.
Pch:文件放的是一些宏定义,一些接口之类
15 . CoreData:
Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,
1.Core Data 是数据持久化存储的最佳方式
2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型
在Mac OS X 10.5Leopard及以后的版本中,开发者也可以通过继承NSPersistentStore类以创建自定义的存储格式
3.好处:能够合理管理内存,避免使用sql的麻烦,高效
4.构成:
(1)NSManagedObjectContext(被管理的数据上下文)
操作实际内容(操作持久层)
作用:插入数据,查询数据,删除数据
(2)NSManagedObjectModel(被管理的数据模型)
数据库所有表格或数据结构,包含各实体的定义信息
作用:添加实体的属性,建立属性之间的关系
操作方法:视图编辑器,或代码
(3)NSPersistentStoreCoordinator(持久化存储助理)
相当于数据库的连接器
作用:设置数据存储的名字,位置,存储方式,和存储时机
(4)NSManagedObject(被管理的数据记录)
相当于数据库中的表格记录
(5)NSFetchRequest(获取数据的请求)
相当于查询语句
(6)NSEntityDescription(实体结构)
相当于表格结构
16 .OC优缺点
优点:
1.Category是非常实用的扩展机制,可以很方便的为一个已有的类添加属性或者方法,而不需要笨拙的去继承。
2.运行时多态的概念,可以让一个类的对象动态的以其他类行为去执行(OC中多了很多运行时态的机制,其中id的特殊用途,可以通过id类型的变量,调用不同类的同名函数,即使这些类没有任何关系)。
3.ARC不用多讲了吧
4.OC中成员变量也有三种访问权限,@public,@protected,@private。但默认的是@protected,而C++中默认是private。
5.OC中成员函数只有两种,一种是实例函数,一种是类函数。实例函数就是C++中的Public函数,类函数就是public中的static函数。
6.OC中成员函数如果要接受多个参数,则需要每个参数前加冒号.
7,OC还有protocol概念, 通过@protocol-@end来声明protocol。类中通过<protocol1,protocol2,...>来表示支持某个协议。如@interface
A : Object < NSCopying, NSTransform >-@end表明类A继承与Object类,并支持两个协议(NSCopying, NSTransform )。
8.由于都是C衍生出的面向对象的语言
所以可以和C++混合编码。(百度地图API 就用到了)
缺点:
- 不支援命名空間
- 不支持运算符重载
- 不支持多重继承
- 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣