首页 > 代码库 > iOS知识点集合
iOS知识点集合
一、前言部分
文中的问题多收集整理自网络,不保证100%准确,还望斟酌采纳。
1、怎样防止指针的越界使用问题?
答案:
1 .防止数组越界,必须让指针指向一个有效的内存地址,
2. 防止向一块内存中拷贝过多的内容
3. 防止使用空指针
4 .防止改变const修改的指针
5. 防止改变指向静态存储区的内容
6. 防止两次释放一个指针
7. 防止使用野指针.
2、http请求方式有哪些?
答案:
1)GET
2)HEAD
3)PUT
4)DELETE
5)POST
6)OPTIONS
3、uiview的圆角属性设置方法?
答案:
1)m_mainImgView.layer.cornerRadius = 具体数值;
2)m_mainImgView.layer.masksToBounds= YES;
4、masksToBounds属性的作用是什么?
答案:
决定子layer是否被当前layer的边界剪切,默认是NO
5、描述iOS程序的运行流程 ?
答案:
1. 系统调用app的main函数
2. main函数调用UIApplicationMain.
3. UIApplicationMain创建sharedapplication instance, UIApplication默认的instance.
4. UIApplicationMain读取Info.plist找到主nib文件, 加载nib,把shared applicationinstance 设为nib的owner.
5. 通过nib文件,创建app的独立UIWindows object.
6. 通过nib,实例化了程序的AppDelegate object.
7. app内部启动结束,application:didFinishLaunchingWith-Options: 被设定成 wAppDelegate instance.
8. AppDelegate向UIWindowinstance发makeKeyAndVisible消息, app界面展示给用户. app准备好接收用户的操作指令.
6、 iOS内存管理的方式有哪些?
答案:
手动管理(MRC) 自动内存管理(ARC)
7、 Object-C有多继承吗?没有的话用什么代替?
答案:
OC 本身是没有多继承的,但是我们可以通过协议来实现类似C++中的多继承。
8、属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
答案:
1. readwrite 是可读可写特性;需要生成getter方法和setter方法时
2. readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
3. assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
4. retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
5. copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。
6. nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,
一般使用nonatomic
9、对于语句NSString*obj = [[NSData alloc] init]; obj在编译时和运行时分别时什么类型的对象?
答案:
编译时是NSString的类型;运行时是NSData类型的对象
10、id 声明的对象有什么特性?
答案:
id 声明的对象具有运行时的特性,即可以指向任意类型的objcetive-c的对象;
11、 原子(atomic)跟非原子(non-atomic)属性有什么区别?
答案:
1. atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
2. non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,
那么访问器只是简单地返回这个值。
12、 类别和类扩展的区别是什么?
答案:
category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category。
13、 在iOS应用中如何保存数据?
答案:
有以下几种保存机制:
1.通过web服务,保存在服务器上
2.通过NSCoder固化机制,将对象保存在文件中
3.通过SQlite或CoreData保存在文件数据库中
14、Object-C有私有方法吗?私有变量呢?
答案:
objective-c– 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象
只暴露有用的东西. 如果没有了私有方法的话,对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法
1 @interface Controller : NSObject { NSString *something; } 2 + (void)thisIsAStaticMethod; 3 – (void)thisIsAnInstanceMethod; 4 @end 5 @interface Controller (private) 6 -(void)thisIsAPrivateMethod; 7 @end
@private可以用来修饰私有变量在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的
15、关键字const什么含义?
答案:
const意味着”只读”,下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)
第四个意思a是一个 指向整型数的常指针(也就是说,指 针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味
着a是一个指向常整型数的常指针(也就是说,指针指向 的整型数是不可修改的,同时指针也是不可修改的)。
结论:
关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的
如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的
垃圾让别人来清理的。)通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。合理地使用关键字const
可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
欲阻止一个变量被改变,可以使用 const 关键字。在定义该const 变量时,通常需要对它进行初始化,因为以后就没有机会再
去改变它了;
2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为 const,或二者同时指定为const;
3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
4)对于类的成员函数,若指定其为const 类型,则表明其是一个常函数,不能修改类的成员变量;
5)对于类的成员函数,有时候必须指定其返回值为const 类型,以使得其返回值不为“左值”。
16、关键字volatile有什么含义?并给出三个不同例子?
答案:
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,
优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3)多线程应用中被几个任务共享的变量
17、一个参数既可以是const还可以是volatile吗?解释为什么。
答案:
是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
18、 一个指针可以是volatile 吗?解释为什么。
答案:
可以是的。
尽管这种情况并不常见,但它还是可以。一个例子就是:
当一个中断服务子程序企图去修改一个指向一个buffer指针的时候。
19、static有什么作用?
答案:
1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时
仍维持上次的值;
2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
20、#import 跟#include 又什么区别,@class呢, #import<> 跟 #import””又什么区别?
答案:
#import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字, 使用#import头文件会自动
只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,
才去查看类的实现文件,可以解决头文件的相互包含;#import<>用来包含系 统的头文件,#import””用来包含用
户头文件。
21、线程和进程的区别?
答案:
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的主要差别
在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,
而线程只是一 个进程中的不同执行路 径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就
等于整个进程死掉,所以多进程的程序要比多线程的程 序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求
同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
22、堆和栈的区别?
答案:
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memoryleak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统
预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的
余空间时,将提示overflow。因 此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,
而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,
也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,
则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部
变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们
手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的
指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
23、介绍一下Object-C的内存管理机制?
答案:
1)当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条
release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2)当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来
确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3)如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.为什么很多
内置的类,如TableViewController的delegate的属性是assign不是retain。
循环引用
所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:
1)对象a创建并引用到了对象b.
2)对象b创建并引用到了对象c.
3)对象c创建并引用到了对象b.
这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,
b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用
通过其他规则来维护引用关系。比如,我们常见的delegate往往是assign方式的属性而不是retain方式 的属性,
赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController对象a
通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,
那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。
24、定义属性时,什么情况使用copy、assign、retain?
答案:
assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,
copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,
a和b各自有自己的内存,就可以解决这个问题。retain 会使计数器加一,也可以解决assign的问题。
另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,
否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
if (property != newValue) { [property release]; property = [newValue retain]; }
25、对象是什么时候被release的?
答案:
引用计数为0时。 autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入
了当前的 Autoreleasepool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop,
系统会隐式创建一个Autoreleasepool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,
在每一个Runloop结束时,当前栈顶的Autoreleasepool会被销毁,这样这 个pool里的每个Object
(就是autorelease的对象)会被release。那什么是一个Runloop呢?一个UI事件,Timercall, delegate call,
都会是一个新的Runloop
26、iOS有没有垃圾回收机制?
答案:
iOS在Objective-c 2.0之后,也提供了垃圾回收机制。但是在iOS移动终端设备中,并不支持垃圾回收机制。
因此,iPhone并不能对内存进行自动垃圾回收处理(autorelease)。因此需要注意 垃圾回收机制并不是ARC,
ARC也是需要管理内存的,只不过是隐式的管理内存,编译器会再适当的地方自动插入retain,release和
autorelease消息。
27、介绍一下tableView的重用机制?
答案:
查看UITableView头文件,会找到NSMutableArray* visiableCells,和NSMutableDictnery* reusableTableCells两个结构。
visiableCells内保存当前显示的cells,reusableTableCells保存可重 用的cells。
TableView显示之初,reusableTableCells为空,那么 tableViewdequeueReusableCellWithIdentifier:CellIdentifier返回nil。
开始的cell都是 通过[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的 次数。比如:有100条数据,iPhone一屏最多显示10个cell。
程序最开始显示TableView的情况是:
1. 用[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10次cell,
并给cell指定同样的重用标识(当然,可以为不同显示类型的 cell指定不同的标识)。并且10个cell全部都加入到visiableCells数组,
reusableTableCells为空。
2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到
visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的 cell,cellForRowAtIndexPath再次
被调用的候,tableViewdequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,
cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以
正常重用了。
28、ViewController 的loadView、viewDidLoad、viewDidUnload分别是什么时候调用的,在自定义
ViewCointroller时在这几个函数中应该做什么工作?
答案:
由init、loadView、viewDidLoad、viewDidUnload、dealloc的关系说起
1)init方法
在init方法中实例化必要的对象(遵从LazyLoad思想)
init方法中初始化ViewController本身
2)loadView方法
当view需要被展示而它却是nil时,viewController会调用该方法。不要直接调用该方法。
如果手工维护views,必须重载重写该方法
如果使用IB维护views,必须不能重载重写该方法
3)loadView和IB构建view
你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候,
view 控制器会收到didReceiveMemoryWarning的消息。默认的实现是检查当前控制器的view是否在使用。 如果它的view
不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法
将被再次调用来创建一个新的view。
4)viewDidLoad方法
viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用。
重载重写该方法以进一步定制view
在iPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引
viewDidLoad后调用数据Model
5)viewDidUnload方法
当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc)
内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后
viewDidUnload方法是更好的方式在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil
(系统release view时已经将其release掉了)在该方法中释放其他与view有关的对象、其他在运行时创建
(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要将
其置为nil,系统release view时已经将其release掉了)一般认为viewDidUnload是viewDidLoad的镜像,因为当view被重新
请求时,viewDidLoad还会重新被执行viewDidUnload中被release的对象必须是很容易被重新创建的对象(比如在
viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象
6)dealloc方法
viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情
29、ViewController的didReceiveMemoryWarning是在什么时候调用的?默认的操作是什么?
答案:
当程序接到内存警告时View Controller将会收到这个消息:didReceiveMemoryWarning从iOS3.0开始,不需要重载这个函数,
把释放内存的代码放到viewDidUnload中去。这个函数的默认实现是:检查controller是否可以安全地释放它的view(这里加粗的
view指的是controller的view属性),比如view本身没有superview并且可以被很容易地重建(从nib或者loadView函数)。
如果view可以被释放,那么这个函数释放view并调用viewDidUnload。你可以重载这个函数来释放controller中使用的其他内存。
但要记得调用这个函数的super实现来允许父类(一般是UIVIewController)释放view。如果你的ViewController保存着
view的子view的引用,那么,在早期的iOS版本中,你应该在这个函数中来释放这些引用。而在iOS3.0或更高版本中,
你应该在viewDidUnload中释放这些引用。
30、列举Cocoa中常见的集中多线程的实现,并谈谈多线程安全的几种解决办法,一般什么地方会用到多线程?
答案:
NSOperation NSThread
@sychonized 一般需要做多任务的处理时会用的多线程。
31、怎么理解MVC,在OC中MVC是怎么实现的?
答案:
MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表特别的知识和专业技能,它们负责保有应用程序
的数据和定义操作数据的 逻辑。视图对象知道如何显示应 用程序的模型数据,而且可能允许用户对其进行编辑。控制器对象
是应用程序的视图对象和模型对象之间的协调者。
32、delegate和notification区别,分别在什么情况下使用?
答案:
delegate针对one-to-one关系,并且reciever可以返回值给sender;
notification 可以针对one-to-one/many/none,reciever无法返回值给sender;
所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。
33、谈谈对KVC(Key-Value-Coding)与KVO(Key-Value-Observing)(键-值-编码 与 键-值-监看)的理解?
答案:
当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。
首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),
如果还没有找到,程序会继续试图调用 -(id)valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,
程序会抛出一个 NSUndefinedKeyException异常错误。(Key-Value Coding查找方法的时候,不仅仅会查找someKey
这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以及 _getsomeKey这几种形式。同时,
查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。)设计valueForUndefinedKey:
方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。
34、self.跟self的区别是什么?
答案:
self. 表示对象的属性 self 表示对象本身
35、id、nil分别代表什么?
答案:
1)id和void *并非完全一样。在上面的代码中,id是指向struct objc_object的一个指针,这个意思基本上是说,id是一个指向任何
一个继承了Object(或者NSObject)类的对象。需要注意的是id 是一个指针,所以你在使用id的时候不需要加星号。
比如id foo=nil定义了一个nil指针,这个指针指向NSObject的一个任意子类。而id *foo=nil则定义了一个指针,这个
指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。
2)nil和C语言的NULL相同,在objc/objc.h中定义。nil表示一个Objctive-C对象,这个对象的指针指向空(没有东西就是空)。
36、内存管理 Autorelease、retain、copy、assign的set方法和含义?
答案:
1)你初始化(alloc/init)的对象,你需要释放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init];
后,需要
[aArray release];
2)你retain或copy的,你需要释放它。例如:
[aArray retain]
后,需要
[aArray release];
3)被传递(assign)的对象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时: 你或希望将对象2进行retain,
以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。
37、谈谈你对于索引计数的理解?
答案:
retain值 = 索引计数(ReferenceCounting) NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载
(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类 (CollectionClasses)
都执行类似操作。例如NSDictionary,甚至UINavigationController。Alloc/init建立的对象,索引计数为1。无需将其再次retain
[NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象所以是本地临时对象,
那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。缺省的类方法返回值都被执行了“自动释放”方法。
(*如上中的NSArray)在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,
而retain值为1的)
38、类别的作用是什么?
答案:
有时我们需要在一个已经定义好的类中增加一些方法,而不想去重写该类。比如,当工程已经很大,代码量比较多,或者类中
已经包住很多方法,已经有其他代码调用了该类创建对象并使用该类的方法时,可以使用类别对该类扩充新的方法。注意:
类别只能扩充方法,而不能扩充成员变量。
39、什么是委托(举例)?
答案:
委托代理(degegate),顾名思义,把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它
来打理要做的事。反映到程序中,首先要明确一个对象的委托 方是哪个对象,委托所做的内容是什么。委托机制是一种设计
模式,在很多语言中都用到的,这只是个通用的思想,网上会有很多关于这方面的介绍。那么在苹果开发过程中,用到委托的
程序实现思想如下,我主要拿如何在视图之间传输信息做个例子。譬如:在两个页面(UIIview视图对象)实现传值,
用委托(delegate)可以很好做到!
方法:
1 //类A 2 @interface A:UIView 3 id transparendValueDelegate; 4 @property(nomatic, retain) idtransparendValueDelegate; 5 @end 6 7 @implemtion A 8 @synthesize transparendValueDelegate 9 -(void)Function 10 { 11 NSString* value = http://www.mamicode.com/@"hello"; 12 //让代理对象执行transparendValue动作 13 [transparendValueDelegate transparendValue:value]; 14 } 15 @end 16 17 //类B 18 @interface B:UIView 19 NSString* value; 20 @end 21 22 @implemtion B 23 -(void)transparendValue:(NSString*)fromValue 24 { 25 value = http://www.mamicode.com/fromValue;"the value is %@",value); 27 } 28 @end 29 30 //下面的设置A代理委托对象为B 31 //在定义A和B类对象处: 32 33 A* a = [[A alloc] init]; 34 B* b = [[B alloc] init]; 35 a. transparendValueDelegate = b;//设置对象a代理为对象b
这样在视图A和B之间可以通过委托来传值!
下面这个例子委托有两类:
1、一个视图类对象的代理对象为父视图,子视图用代理实现让父视图显示别的子视图
2、同一父视图下的一个子视图为另一个子视图的代理对象,让另一个子视图改变自身背景色为给定的颜色
===============================================
规范格式如下:
1 @protocol TransparendValueDelegate; 2 3 @interface A:UIView 4 id< TransparendValueDelegate > m_dTransparendValueDelegate; 5 @property(nomatic, retain) id m_dTransparendValueDelegate; 6 @end 7 //代理协议的声明 8 @protocol TransparendValueDelegat<NSObject> 9 { 10 -(void)transparendValue:(NSString*)fromValue; 11 12 }
40、frame 和 bounds 的区别 ,bound的大小改变frame 改变吗?
答案:
frame:该view在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统)
bounds:该view在本地坐标系统中的位置和大小。(参照点是,本地坐标系统)
41、异步请求最大数目是多大,为什么只能这么多?
答案:
这个数量是跟cpu有关的,并发性取决于cpu核数,每个核只能 同时处理一个任务.4核cpu理论上可以并发处理4个任务,
如果按http来算就是4个请求,但是cpu是抢占式资源,所以一般来说并发量是要根据任务的 耗时和cpu的繁忙度来计算4个左右
只是个经验值你开10个短耗时的任务和几个长耗时任务的效率是不同的- -..一般来说估算这个量的最大效率估算公示是cpu
核数*2-1,这个公式是当时对集群进行压测得到的结论.cpu抢占时间跟任务时长…开启这个数量的 线程可以最大化的榨干cpu
一个道理。cpu不可能都被抢去做connection.iOS是cpu密集型的消耗?。这个大概知道就行了,也不会有人特 别在意吧…
cpu核数*2-1那个是做淘宝的java团队压测得到的线程最优数?,放在iOS上也多少适用…一般来说不超过这个量就好,
线程不是起的越多越好,线程数就是…cpu来决定的
42、 什么是coredata ?
答案:
coredata是苹果提供一套数据保存框架,其基于SQlite
43、 什么是NSManagedObject模型?
答案:
NSManagedObject是NSObject的子类 ,也是coredata的重要组成部分,它是一个通用的类,实现了
core data 模型层所需的基本功能,用户可通过子类化NSManagedObject,建立自己的数据模型。
44、 什么是NSManagedobjectContext ?
答案:
NSManagedobjectContext对象负责应用和数据库之间的交互。
45、什么时候使用NSMutableArray,什么时候使用NSArray?
答案:
当数组在程序运行时,需要不断变化的,使用NSMutableArray,当数组在初始化后,便不再改变的
使用NSArray。需要指出的是,使用NSArray只表明的是该数组在运行 时不发生改变,即不能往
NSAarry的数组里新增和删除元素,但不表明其数 组內的元素的内容不能发生改变。NSArray是线程安
全的,NSMutableArray不是线程安全的,多线程使用到NSMutableArray需 要注意。
46、 @property 后面可以有哪些修饰符?
答案:
读 、写性修饰符:readwrite | readonly
setter相关修饰符:assign | retain | copy
原子性修饰符:atomic | nonatomic
getter和setter修饰符
47、怎么用 copy 关键字?
答案:
48、 如何重写带 copy 关键字的 setter?
答案:
以上面的为例 @property (copy) NSstring *str;
-(void)setStr:(nsstring *)str{ _str = [str copy]; }
49、 如何让自己的类用 copy 修饰符?
答案:
在使用字符串或block的时候用copy修饰,在网上有人觉得有另外一种理解问题的
方式就是理解成如何要自己的类也支持copy功能,这样的话要答遵从NSCopying协议,然后实现
50、什么情况使用 weak 关键字,相比 assign 有什么不同?
答案:
assign 修饰 基本数据类型
weak 修饰 弱指针对象
51、请简要说明viewDidLoad和viewDidUnload何时调用
答案:
viewDidLoad在view从nib文件初始化时调用,loadView在controller的view为nil时调用。
此方法在编程实现view时调用,view控制器默认会注册memory warning notification,
当view controller的任何view没有用的时候,viewDidUnload会被调用,在这里实现将retain
的view release,如果是retain的IBOutlet view 属性则不要在这里release,IBOutlet会负责release 。
52、在一个对象的方法里面:self.name= “object”;和 name =”object” 有什么不同?
答案:
self.name =”object”:会调用对象的setName()方法;
name = “object”:会直接把object赋值给当前对象的name属性。
53、请简述self.name= nil的机制,以及与[name release]的区别?
答案:
self.name =nil; //使用nil参数调用setName:方法
[name release] 生成的访问器将自动释放以前的name对象
54、#import和#include的区别 @class?
答案:
@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文 件中还是需要使用#import
而#import比起#include的好处就是不会引起交叉编译
55、单件实例是什么?
答案:
Foundation 和 Application Kit 框架中的一些 类 只允 许创 建 单 件 对 象,即 这 些 类 在当前 进 程中的唯一 实 例。
举 例来 说 ,NSFileManager 和NSWorkspace 类 在使用时 都是基于 进 程 进 行 单 件 对 象的 实 例化。当向 这 些
类请 求 实 例的 时 候,它 们会向您 传递单 一 实 例的一个引用,如果 该实 例 还 不存在, 则 首先 进 行 实 例的分配
和初始化。 单 件 对 象充当控制中心的角色, 负责 指引或 协调类 的各种服 务 。如果 类 在概念上只有一个 实 例(比如
NSWorkspace ),就 应该产 生 一个 单 件 实 例,而不是多个 实 例;如果将来某一天可能有多个 实 例,您可以使用 单
件 实 例机制,而不是工厂方法或函数。
56、简单描述下 SDWebImage的原理,实现机制。
答案:
-
入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
-
进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
-
先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
-
SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
-
如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
-
根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
-
如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
-
如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
-
共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
-
图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
-
connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
-
connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
-
图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
-
在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
-
imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
-
通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
-
将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
-
SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
-
SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
-
SDWebImagePrefetcher 可以预先下载图片,方便后续使用。
从上面流程可以看出,当你调用setImageWithURL:方法的时候,他会自动去给你干这么多事,当你需要在某一具体时刻做事情的时候,
你可以覆盖这些方法。比如在下载某个图片的过程中要响应一个事件,就覆盖这个方法(对于初级来说,用sd_setImageWithURL:的若干个方法就可以实现很好的图片缓存):
57、层和UIView的区别是什么?
答案:
两者最大的区别是,图层不会直接渲染到屏幕上,UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。
它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器。
一个UIView上可以有n个CALayer,每个layer显示一种东西,增强UIView的展现能力。
58、What is lazy loading?
答案:懒加载模式,只在用到的时候才去初始化,也可以理解成延时加载。我觉得最好也最简单的一个列子就是tableView中图片的加载显示了。
一个延时载,避免内存过高,一个异步加载,避免线程堵塞。
59、简叙TCP/UDP区别与联系
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,
之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,
但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,
故而传输速度很快 TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,
必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,我们来看看这三次对话的简单过程:
1.主机A向主机B发出连接请求数据包;
2.主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包;
3.主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,
经过三次“对话”之后,主机A才向主机B正式发送数据。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!
UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境, tcp协议和udp协议的差别 是否连接面向连接面向非连接 传输可靠性可靠不可靠
应用场合传输大量数据少量数据速度慢快.
60、socket连接和http连接的区别
答案:
简单说,你浏览的网页(网址以http://开头)都是http协议传输到你的浏览器的, 而http是基于socket之上的。
socket是一套完成tcp,udp协议的接口。
HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的
tcp协议: 对应于传输层
ip协议: 对应于网络层
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
http连接:http连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉;
socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,
比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。
所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的。
61、请描述URL
答案:
HTTP URL (URL是一种特殊类型的URI是他的子类,包含了用于查找某个资源的足够的信息)的格式如下:
http://host[":"port][abs_path]
http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port指定一个端口号,
为空则使用缺省端口80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,
必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。
62、什么是TCP连接的三次握手?
答案:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,
此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入
ESTABLISHED状态,完成三次握手。握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器
和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)
63、简述 NULL、nil、Nil、NSNull 的区别?
答案:
1、NULL是C语言中的空指针。
2、nil是OC中指向空对象的指针。
3、Nil是OC指向类的空指针。
4、NSNull是在数组或字典集合对象中表示空值对象。
64、什么是指针的释放?
答案:
1 释放该指针指向的内存,只有堆上的内存才需要我们手工释放,栈上不需要.
2 将该指针重定向为NULL.
65、HTTP协议详解
答案:
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。目前在WWW中使用的是HTTP/1.0的第六版,
HTTP/1.1的规范化工作正在进行之中,http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,
HTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,
这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
66、简叙RunLoop 与RunTime的区别
答案:
一.RunLoop:
Runloop是事件接收和分发机制的一个实现。
Runloop提供了一种异步执行代码的机制,不能并行执行任务。
在主队列中,Main RunLoop直接配合任务的执行,负责处理UI事件、定时器以及其他内核相关事件。
1).RunLoop的主要目的:
保证程序执行的线程不会被系统终止。
2).什么时候使用Runloop ?
当需要和该线程进行交互的时候才会使用Runloop.
每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop
添加至少一个事件源,然后去run它。 一般情况下我们是没有必要去启用线程的RunLoop的,除非你在
一个单独的线程中需要长久的检测某个事件。主线程默认有Runloop。当自己启动一个线程,如果只是用于
处理单一的事件,则该线程在执行完之后就退出了。 所以当我们需要让该线程监听某项事务时,就得让线程一
直不退出,runloop就是这么一个循环,没有事件的时候,一直卡着,有事件来临了,执行其对应的函数。
RunLoop,正如其名所示,是线程进入和被线程用来相应事件以及调用事件处理函数的地方.需要在代码中使用控制
语句实现RunLoop的循环,也就是说,需要代码提供while或者for循环来驱动RunLoop.在这个循环中,使用一个runLoop
对象[NSRunloop currentRunloop]执行接收消息,调用对应的处理函数. Runloop接收两种源事件:input sources和timer sources。
input sources 传递异步事件,通常是来自其他线程和不同的程序中的消息; timer sources(定时器) 传递同步事件(重复执行或者在
特定时间上触发)。除了处理input sources,Runloop 也会产生一些关于本身行为的notificaiton。注册成为Runloop的observer,
可以接收到 这些notification,做一些额外的处理。(使用CoreFoundation来成为runloop的observer)。
Runloop工作的特点:
1>当有时间发生时,Runloop会根据具体的事件类型通知应用程序作出相应的反应;
2>当没有事件发生时,Runloop会进入休眠状态,从而达到省电的目的;
3>当事件再次发生时,Runloop会被重新唤醒,处理事件.
提示:一般在开发中很少会主动创建Runloop,而通常会把事件添加到Runloop中.
二.Runtime:
RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决
定调用哪个函数(C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。
属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编译阶段,OC可以调用任何函数,即使这个函
数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。
举例说明:
比如你[obj makeText];
则运行时就这样的:首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector (makeText));,在objc_msgSend函数
中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以
SEL为key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,
则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数
中去执行。
如果您觉得阅读完本文对您有帮助,请点一下“推荐”按钮,您的推荐将是我写作的最大动力;本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/ChinaKingKong/欢迎各位转载,但未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接否则保留追究法律责任的权利。
iOS知识点集合