中国建设银行移动门户网站,个人怎么申请注册商标,平面设计公司理念,网络制作公司专业制作网站1、Object-C有多继承吗#xff1f;没有的话用什么代替#xff1f;cocoa 中所有的类都是NSObject 的子类 多继承在这里是用protocol 委托代理 来实现的 你不用去考虑繁琐的多继承 ,虚基类的概念. ood的多态特性 在 obj-c 中通过委托来实现. 2、Object-C有私有方法吗#xff1…1、Object-C有多继承吗没有的话用什么代替cocoa 中所有的类都是NSObject 的子类 多继承在这里是用protocol 委托代理 来实现的 你不用去考虑繁琐的多继承 ,虚基类的概念. ood的多态特性 在 obj-c 中通过委托来实现. 2、Object-C有私有方法吗私有变量呢 objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法 interface Controller : NSObject { NSString *something; } (void)thisIsAStaticMethod; – (void)thisIsAnInstanceMethod; end interface Controller (private) - (void)thisIsAPrivateMethod; end private可以用来修饰私有变量 在Objective‐C中所有实例变量默认都是私有的所有实例方法默认都是公有的 3、关键字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 类型以使得其返回值不为“左值”。 4、关键字volatile有什么含义并给出三个不同例子 一个定义为volatile的变量是说这变量可能会被意想不到地改变这样编译器就不会去假设这个变量的值了。精确地说就是优化器在用到 这个变量时必须每次都小心地重新读取这个变量的值而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子 并行设备的硬件寄存器如状态寄存器 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 多线程应用中被几个任务共享的变量 一个参数既可以是const还可以是volatile吗解释为什么。 一个指针可以是volatile 吗解释为什么。 下面是答案 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。 static作用 函数体内 static 变量的作用范围为该函数体不同于 auto 变量该变量的内存只被分配一次 因此其值在下次调用时仍维持上次的值 2在模块内的 static 全局变量可以被模块内所用函数访问但不能被模块外其它函数访问 3在模块内的 static 函数只可被这一模块内的其它函数调用这个函数的使用范围被限制在声明 它的模块内 4在类中的 static 成员变量属于整个类所拥有对类的所有对象只有一份拷贝 5在类中的 static 成员函数属于整个类所拥有这个函数不接收 this 指针因而只能访问类的static 成员变量。 6、#import和#include的区别class代表什么 class一般用于头文件中需要声明该类的某个实例变量的时候用到在m文件中还是需要使用#import 而#import比起#include的好处就是不会引起重复包含 7、线程和进程的区别 进程和线程都是由操作系统所体会的程序运行的基本单元系统利用该基本单元实现系统对应用的并发性。 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间一个进程崩溃后在保护模式下不会对其它进程产生影响而线程只是一 个进程中的不同执行路径。线程有自己的堆栈和局部变量但线程之间没有单独的地址空间一个线程死掉就等于整个进程死掉所以多进程的程序要比多线程的程 序健壮但在进程切换时耗费资源较大效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作只能用线程不能用进程。 8、堆和栈的区别 管理方式对于栈来讲是由编译器自动管理无需我们手工控制对于堆来说释放工作由程序员控制容易产生memory leak。 申请大小 栈在Windows下,栈是向低地址扩展的数据结构是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的在 WINDOWS下栈的大小是2M也有的说是1M总之是一个编译时就确定的常数如果申请的空间超过栈的剩余空间时将提示overflow。因 此能从栈获得的空间较小。 堆堆是向高地址扩展的数据结构是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的自然是不连续的而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见堆获得的空间比较灵活也比较大。 碎片问题对于堆来讲频繁的new/delete势必会造成内存空间的不连续从而造成大量的碎片使程序效率降低。对于栈来讲则不会存在这个问题因为栈是先进后出的队列他们是如此的一一对应以至于永远都不可能有一个内存块从栈中间弹出 分配方式堆都是动态分配的没有静态分配的堆。栈有2种分配方式静态分配和动态分配。静态分配是编译器完成的比如局部变量的分配。动态分配由alloca函数进行分配但是栈的动态分配和堆是不同的他的动态分配是由编译器进行释放无需我们手工实现。 分配效率栈是机器系统提供的数据结构计算机会在底层对栈提供支持分配专门的寄存器存放栈的地址压栈出栈都有专门的指令执行这就决定了栈的效率比较高。堆则是C/C函数库提供的它的机制是很复杂的。 9、Object-C的内存管理 1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁. 2.当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它. 3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等. 10、为什么很多内置的类如TableViewController的delegate的属性是assign不是retain 循环引用 所有的引用计数系统都存在循环应用的问题。例如下面的引用关系 对象a创建并引用到了对象b. 对象b创建并引用到了对象c. 对象c创建并引用到了对象b. 这时候b和c的引用计数分别是2和1。当a不再使用b调用release释放对b的所有权因为c还引用了b所以b的引用计数为1b不会被释放。b不释放c的引用计数就是1c也不会被释放。从此b和c永远留在内存中。 这种情况必须打断循环引用通过其他规则来维护引用关系。比如我们常见的delegate往往是assign方式的属性而不是retain方式的属 性赋值不会增加引用计数就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController 对象a通 过retain获取了UITableView对象b的所有权这个UITableView对象b的delegate又是a如果这个delegate是 retain方式的那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时也要注意这点。 11、定义属性时什么情况使用copy、assign、retain assign用于简单数据类型如NSInteger,double,bool, retain和copy用于对象 copy用于当a指向一个对象b也想指向同样的对象的时候如果用assigna如果释放再调用b会crash,如果用copy 的方式a和b各自有自己的内存就可以解决这个问题。 retain 会使计数器加一也可以解决assign的问题。 另外atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下原子操作是必要的否则有可能引起错误的结果。 加了atomicsetter函数会变成下面这样 if (property ! newValue) { [property release]; property [newValue retain]; } 12、对象是什么时候被release的 引用计数为0时。 autorelease实际上只是把对release的调用延迟了对于每一个Autorelease系统只是把该Object放入了当前的 Autorelease pool中当该pool被释放时该pool中的所有Object会被调用Release。对于每一个Runloop系统会 隐式创建一个Autorelease pool这样所有的release pool会构成一个象CallStack一样的一个栈式结构在每一个 Runloop结束时当前栈顶的Autorelease pool会被销毁这样这个pool里的每个Object就是autorelease的对 象会被release。那什么是一个Runloop呢一个UI事件Timer call delegate call 都会是一个新的 Runloop 13、iOS有没有垃圾回收 Objective-C 2.0也是有垃圾回收机制的但是只能在Mac OS X Leopard 10.5 以上的版本使用。 14、tableView的重用机制 查看UITableView头文件会找到NSMutableArray* visiableCells和 NSMutableDictnery* reusableTableCells两个结构。visiableCells内保存当前显示的 cellsreusableTableCells保存可重用的cells。 TableView显示之初reusableTableCells为空那么 tableView dequeueReusableCellWithIdentifier: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加入到visiableCellscell1移出visiableCellscell1加入到reusableTableCells。 3.接着向下拖动tableView因为reusableTableCells中已经有值所以当需要显示新的 cellcellForRowAtIndexPath再次被调用的时 候tableView dequeueReusableCellWithIdentifier:CellIdentifier返回cell1。 cell1加入到visiableCellscell1移出reusableTableCellscell2移出 visiableCellscell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。 15、ViewController 的loadView、viewDidLoad、viewDidUnload分别是什么时候调用的在自定义ViewCointroller时在这几个函数中应该做什么工作 由init、loadView、viewDidLoad、viewDidUnload、dealloc的关系说起 init方法 在init方法中实例化必要的对象遵从LazyLoad思想 init方法中初始化ViewController本身 loadView方法 当view需要被展示而它却是nil时viewController会调用该方法。不要直接调用该方法。 如果手工维护views必须重载重写该方法 如果使用IB维护views必须不能重载重写该方法 loadView和IB构建view 你在控制器中实现了loadView方法那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候 view 控制器会收到 didReceiveMemoryWarning的消息。 默认的实现是检查当前控制器的view是否在使用。如果它的view不在当前正在使用的 view hierarchy里面且你的控制器实现了loadView方法那么这个view将被release, loadView方法将被再次调用 来创建一个新的view。 viewDidLoad方法 viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用。 重载重写该方法以进一步定制view 在iPhone OS 3.0及之后的版本中还应该重载重写viewDidUnload来释放对view的任何索引 viewDidLoad后调用数据Model viewDidUnload方法 当系统内存吃紧的时候会调用该方法注viewController没有被dealloc 内存吃紧时在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式但是OS 3.0及以后viewDidUnload方法是更好的方式 在该方法中将所有IBOutlet无论是property还是实例变量置为nil系统release view时已经将其release掉了 在该方法中释放其他与view有关的对象、其他在运行时创建但非系统必须的对象、在viewDidLoad中被创建的对象、缓存数据 等 release对象后将对象置为nilIBOutlet只需要将其置为nil系统release view时已经将其release掉了 一般认为viewDidUnload是viewDidLoad的镜像因为当view被重新请求时viewDidLoad还会重新被执行 viewDidUnload中被release的对象必须是很容易被重新创建的对象比如在viewDidLoad或其他方法中创建的对象不要release用户数据或其他很难被重新创建的对象 dealloc方法 viewDidUnload和dealloc方法没有关联dealloc还是继续做它该做的事情 16、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中释放这些引用。 17、列举Cocoa中常见的集中多线程的实现并谈谈多线程安全的几种解决办法一般什么地方会用到多线程 NSThread,GCD等。尽量用上层分装好的方法去实现多线程而不是手动调用NSThread。 18、怎么理解MVC在Cocoa中MVC是怎么实现的 Model: 代表你的应用程序是什么不是怎么展现 Controller: 控制你的Model怎么展现给用户UI逻辑 View: Controller的奴隶。。。 1 ModelControllerView相互通讯的规则 Controller可以直接和Model通信 Controller也可以直接和View通信 Model和View永远不能直接通信 iOS中View和Controller的通信是透明和固定的主要通过outlet和action实现 View使用Delegate接口和Controller同步信息 View不直接和数据通信使用dataSource接口从Controller处获取数据 View的delegate和dataSource一般就是Controller Controller负责为View翻译和格式化Model的数据 Model使用Notification KVO的方式分发数据更新信息Controller可以有选择的监听自己感兴趣的信息。 View也可以监听广播信息但一般不是Model发出的信息 一个完整的App就是很多MVC的集合 19、delegate和notification区别分别在什么情况下使用 Delegate: 消息的发送者(sender)告知接收者(receiver)某个事件将要发生delegate同意然然后发送者响应事件delegate机制使得接收者可以改变发送者的行为。通常发送者和接收者的关系是直接的一对多的关系。 Notification: 消息的发送者告知接收者事件已经发生或者将要发送仅此而已接收者并不能反过来影响发送者的行为。通常发送者和接收者的关系是间接的多对多关系。 1. 效率肯定是delegate比nsnotification高。 2. delegate方法比notification更加直接最典型的特征是delegate方法往往需要关注返回值也就是delegate方法 的结果。比如-windowShouldClose:需要关心返回的是yes还是no。所以delegate方法往往包含should这个很传神的词。 也就是好比你做我的delegate我会问你我想关闭窗口你愿意吗你需要给我一个答案我根据你的答案来决定如何做下一步。相反 的notification最大的特色就是不关心接受者的态度我只管把通告放出来你接受不接受就是你的事情同时我也不关心结果。所以 notification往往用did这个词汇比如NSWindowDidResizeNotification那么nswindow对象放出这个 notification后就什么都不管了也不会等待接受者的反应。 1两个模块之间联系不是很紧密就用notification传值例如多线程之间传值用notificaiton。 2delegate只是一种较为简单的回调且主要用在一个模块中例如底层功能完成了需要把一些值传到上层去就事先把上层的函数通过 delegate传到底层然后在底层call这个delegate它们都在一个模块中完成一个功能例如 说 NavgationController 从 B 界面到A 点返回按钮 (调用popViewController方法) 可以用delegate 比较好。 20、self.跟self什么区别 我们在官方文档里看到这样的代码: 在MyClass.h文件中 interface MyClass : NSObject { MyObject *myObject; }property (nonatomic, retain) MyObject *myObject;end 在MyClass.m文件中synthesize myObject;-(id)init{if(self [super init]){MyObject * aMyObject [[MyObject alloc] init];self.myObject aMyObject;[aMyObject release];}return self;} 为什么要用之上的赋值方法呢难道self.myObject [[MyObject alloc] init]; 或者 myObject [[MyObject alloc] init]; 不可以吗不要以讹传讹以下是我的一些见解。 第一种当加上self.的时候.................................. MyObject * aMyObject [[MyObject alloc] init]; //aMyObject retainCount 1;self.myObject aMyObject; //myObject retainCount 2;[aMyObject release]; //myObject retainCount 1; 第二种当不加self.的时候MyObject * aMyObject [[MyObject alloc] init]; //aMyObject retainCount 1;myObject aMyObject; //myObject retainCount 1;[aMyObject release]; //myObject被释放; 21、id、nil代表什么 id和void *并非完全一样。在上面的代码中id是指向struct objc_object的一个指针这个意思基本上是说id是一个指向任何 一个继承了Object或者NSObject类的对象。需要注意的是id是一个指针所以你在使用id的时候不需要加星号。比如id foonil 定义了一个nil指针这个指针指向NSObject的一个任意子类。而id *foonil则定义了一个指针这个指针指向另一个指针被指向的这个 指针指向NSObject的一个子类。 nil和C语言的NULL相同在objc/objc.h中定义。nil表示一个Objctive-C对象这个对象的指针指向空没有东西就是空。 首字母大写的Nil和nil有一点不一样Nil定义一个指向空的类是Class而不是对象。 SEL是“selector”的一个类型表示一个方法的名字 Method我们常说的方法表示一种类型这种类型与selector和实现(implementation)相关 IMP定义为 id (*IMP) (id, SEL, …)。这样说来 IMP是一个指向函数的指针这个被指向的函数包括id(“self”指针)调用的SEL方法名再加上一些其他参数.说白了IMP就是实现方法。 22、内存管理 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的一个自动释放的值或传递一个基本数据类型(NSIntegerNSString)时你或希望将对象2进行retain以防止它在被使用之前就被自动释放掉。但是在retain后一定要在适当的时候进行释放。 关于索引计数(Reference Counting)的问题 retain值 索引计数(Reference Counting) NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候所有数组中的对象会被 执行一次释放(retain值减一)。不仅仅是NSArray任何收集类(Collection Classes)都执行类似操作。例如 NSDictionary甚至UINavigationController。 Alloc/init建立的对象索引计数为1。无需将其再次retain。 [NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象但是也是一个自动释放对象。所以是本地临时对象那么无所谓了。如果是打算在全Class中使用的变量(iVar)则必须retain它。 缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray) 在类中的卸载方法“dealloc”中release所有未被平衡的NS对象。(*所有未被autorelease而retain值为1的) 23、类别的作用 有时我们需要在一个已经定义好的类中增加一些方法而不想去重写该类。比如当工程已经很大代码量比较多或者类中已经包住很多方法已经有其他代码调用了该类创建对象并使用该类的方法时可以使用类别对该类扩充新的方法。 注意类别只能扩充方法而不能扩充成员变量。 24、委托举例 委托代理degegate顾名思义把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理代替它来打理要做的事。反映到程序中首先要明确一个对象的委托方是哪个对象委托所做的内容是什么。 委托机制是一种设计模式在很多语言中都用到的这只是个通用的思想网上会有很多关于这方面的介绍。 那么在苹果开发过程中用到委托的程序实现思想如下我主要拿如何在视图之间传输信息做个例子。 譬如在两个页面UIIview视图对象实现传值用委托delegate可以很好做到 方法 类A interface AUIView id transparendValueDelegate; property(nomatic, retain) id transparendValueDelegate; end implemtion A synthesize transparendValueDelegate -(void)Function { NSString* value hello; //让代理对象执行transparendValue动作 [transparendValueDelegate transparendValue: value]; } end 类B interface BUIView NSString* value; end implemtion B -(void)transparendValue:(NSString*)fromValue { value fromValue; NSLog(the value is % ,value); } end //下面的设置A代理委托对象为B //在定义A和B类对象处 A* a [[A alloc] init]; B* b [[B alloc] init]; a. transparendValueDelegate b;//设置对象a代理为对象b 这样在视图A和B之间可以通过委托来传值 25、retainCount 26..属性readwritereadonlyassignretaincopynonatomic 各是什么作用在那种情况下用 assign指定setter方法用简单的赋值这是默认操作。你可以对标量类型如int使用这个属性。你可以想象一个float它不是一个对象所以它不能retain、copy。 retain指定retain应该在后面的对象上调用前一个值发送一条release消息。你可以想象一个NSString实例它是一个对象而且你可能想要retain它。 copy指定应该使用对象的副本深度复制前一个值发送一条release消息。基本上像retain但是没有增加引用计数是分配一块新的内存来放置它。 readonly将只生成getter方法而不生成setter方法getter方法没有get前缀。 readwrite默认属性将生成不带额外参数的getter和setter方法setter方法只有一个参数。 atomic对于对象的默认属性就是setter/getter生成的方法是一个原子操作。如果有多个线程同时调用setter的话不会出现某一个线程执行setter全部语句之前另一个线程开始执行setter的情况相关于方法头尾加了锁一样。 nonatomic不保证setter/getter的原子性多线程情况下数据可能会有问题。 27.类变量的protected ,private ,public ,package声明各有什么含义 Objective-C 对存取权限的设定。也是变量的作用域。 protected 该类和所有的子类中的方法可以直接访问这样的变量这是默认的。 private — 该类中的方法可以访问这样的变量子类不可以。 public — 除了自己和子类中的方法外也可以被其他类或者其他模块中的方法所访问。开放性最大。 package — 对于64位图像这样的成员变量可以在实现这个类的图像中随意访问。 28.浅拷贝和深拷贝区别是什么 简单的来说就是在有指针的情况下浅拷贝只是增加了一个指针指向已经存在的内存而深拷贝就是增加一个指针并且申请一个新的内存使这个增加的指针指向这个新的内存采用深拷贝的情况下释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误 29.Cocoa中与虚基类的概念么怎么简洁的实现 30.NSString 和 NSMutableString 有什么区别 NSString相当于一个const char* 不可以改变。 而 NSMutableString相当于 char* 可以改变内部的内容。 31.自动释放池跟GC有什么区别iPhone上有GC么pool release 和pool drain有什么区别 ”Autorelease Pools”(自动释放池)在应用中的使用技巧。 1Autorelease Pools概要 一个”Autorelease Pool”实例中“包含”其它各种调用了”autorelease”方法的对象。当它释放时其中所有被管理对象都会收 到”relrease”的消信。注意同一个对象可以被多次调用”autorelease”方法并可以放到同一个”Autorelease Pool” 中。引入这个自动释放池机制对象的”autorelease”方法代替”relrease”方法可以延长它的生命周期直接到当 前”Autorelrease Pool”释放。如果想让此对象的生命周期超过”Autorelease Pool”还可以再次”retain”呵 呵有意思吧?且让我慢慢道来。 Cocoa总是认为当前至少有一个”Autorelease Pool”对象是可用的。若此对象并不存在你调用的”autorelease”的所有对象都不会被自动释放掉可想而知造成内存泄露。Cocoa把这个错误信息写入日志??仅仅是为了以后分析。 你可以用”alloc”与”init”方法创建一个”NSAutoreleasePool”对象并且可以调用”release”或”drain” ”release”与”drain”的区别是”drain”在有GC的环境中会引起GC回收操作”release”反之。但在非GC环境中两者相 同。官方的说法是为了程序的兼容性应该考虑用”drain”代替”release”方法来回收它调用它的”autorelease” 或”retain”方法会引起异常。在一个完整的上下文最后”Autorelease Pool”对象应该被”release”掉在方法内或一段循环 体内创建的”Autorelease Pool”对象。 “Autorelease Pools”的所有实例在栈中管理我们暂时叫他“自动释放池栈”并且它们是可以被嵌套的父生子子生孙。。。子子孙 孙 ^_^。例如当我们创建一个”Autorelease Pool”对象后它就被自动放到“自动释放池栈”的栈顶。当本池对象回收时它就随之从 这个栈中POP掉。那么也就是说当任何一个对象调用”autorelease”方法后它会被放入当前线程中当前栈顶的自动释放池中。 接下来我们聊聊”Autorelease Pools”的嵌套问题。在你的应用中你可以任意多的创建”Autorelease Pool”对象而这些 对象被当前线程的“自动释放池栈”所管理。那么除了一个接一个的顺序创建并销毁它的情况外还有一种使用方式就是嵌套式的创建与使用。例如在你的主函 数创建了一个”autorelease pool”然后又调用了创建了”autorelease pool”实例的其它方法或是在外循环中创建 了”Autorelease Pool”的实例而内循环中也做了相同的事情。有意思吧呵呵嵌套的机制使父Pool实例释放后它的所有子Pool也 将释放。但这里还存在一些副作用后续文章会详细讨论。 “Application kit”在一个事件循环里会自动创建一个”autorelease pool”。像鼠标键的按下与释放所以你编写的代码通常不需要考虑太多这方面的事情。当然有以下三种情况你会创建与销毁自己的Pool实例 1应用不是基于”Application Kit”像”Command-line tool”因为它并没有内置的”autorelease pools”的支持。 2创建线程你必需在线程开始时创建一个”Autorelease Pool”实例。反之会造成内存池露会在以后的文章详细说明线程与池的技巧。 3一个循环内创建了太多的临时对象你应该为他们创建一个”Autorelease Pool”对象并在下次循还前销毁它们。 2自动释放池中的”Non-AppKit”应用 在”Non-AppKit”应用中使用自动释放池的机制其实是相当简单的事情。你仅仅需要在main()起始处创建”Autorelease Pool” 对象并在结尾处释放掉它。就像在Xcode的Foundation Tool的创建模版里写的一样。这个确保你在应用生命周期内至少有一 个”Autorelease Pool”是可用的。但是这也使所有在此期间的所有”autorelease”的对象都必需在应用结束后才被释放。这也许 会引起在应用的使用中不断的增长所以你仍然考虑在不同的作用域创建新的”Autorelease Pool”。 大多应用中都存在各种级别的循环机制。在这些应用中你可以在每个循环内的开头创建一个”Autorelease Pool”对象并在结尾处释放掉它。 例如 void main() { NSAutoreleasePool *pool [[NSAutoreleasePool alloc] init]; NSArray *args [[NSProcessInfo processInfo] arguments]; unsigned count, limit [args count]; for (count 0; count limit; count) { NSAutoreleasePool *loopPool [[NSAutoreleasePool alloc] init]; NSString *fileContents; NSString *fileName; fileName [args objectAtIndex:count]; fileContents [[[NSString alloc] initWithContentsOfFile:fileName] autorelease]; // this is equivalent to using stringWithContentsOfFile: [loopPool release]; } [pool drain]; exit (EXIT_SUCCESS); } 在命令行中处理所有以参数传来的文件。一次循环处理一个文件。在循环的开头创建一个”NSAutoreleasePool”对象并在循环结束时释放掉。 因此任何在其中创建并调用“autorelease”的对象都将添加到这个Pool实例中当本池被释放后这些对象也将被回收。注意任何在作用域内 创建的”autoreleased”对象像”fileName”虽然并没有显示的调用”autorelease”方法但都将被当前池所管理并释 放。 32.C和obj-c 如何混用 1obj-c的编译器处理后缀为m的文件时可以识别obj-c和c的代码处理mm文件可以识别obj-c,c,c代码但cpp文件必须只能用c/c代码而且cpp文件include的头文件中也不能出现obj-c的代码因为cpp只是cpp 2)在mm文件中混用cpp直接使用即可所以obj-c混cpp不是问题 3在cpp中混用obj-c其实就是使用obj-c编写的模块是我们想要的。 如果模块以类实现那么要按照cpp class的标准写类的定义头文件中不能出现obj-c的东西包括#import cocoa的。实现文件中即类的实现代码中可以使用obj-c的东西可以import,只是后缀是mm。 如果模块以函数实现那么头文件要按c的格式声明函数实现文件中c函数内部可以用obj-c但后缀还是mm或m。 总结只要cpp文件和cpp include的文件中不包含obj-c的东西就可以用了cpp混用obj-c的关键是使用接口而不能直接使用实现代 码实际上cpp混用的是obj-c编译后的o文件这个东西其实是无差别的所以可以用。obj-c的编译器支持cpp 33.响应者链是什么 响应者链是Application Kit事件处理架构的中心机制。它由一系列链接在一起的响应者对象组成事件或者动作消息可以沿着这些对象进行传 递。如图6-20显示的那样如果一个响应者对象不能处理某个事件或动作也就是说它不响应那个消息或者不认识那个事件则将该消息重新发送给链中的 下一个响应者。消息沿着响应者链向上、向更高级别的对象传递直到最终被处理如果最终还是没有被处理就会被抛弃。 当Application Kit在应用程序中构造对象时会为每个窗口建立响应者链。响应者链中的基本对象是NSWindow对象及其视图层次。在视图层次中级别较低的视图将比级别更高的视图优先获得处理事件或动作消息的机会。NSWindow中保有一个第一响应者的引用它通常是当前窗口中处于选择状态的视图窗口通常把响应消息的机会首先给它。对于事件消息响应者链通常以发生事件的窗口对应的NSWindow对象作为结束虽然其它对象也可以作为下一个响应者被加入到NSWindow对象的后面。 34..UIscrollVew用到了什么设计模式还能再foundation库中找到类似的吗 组合模式composition所有的container view都用了这个模式 观察者模式observer所有的UIResponder都用了这个模式。 模板(Template)模式所有datasource和delegate接口都是模板模式的典型应用 33. .timer的间隔周期准吗为什么怎样实现一个精准的timer? NSTimer可以精确到50-100毫秒. NSTimer不是绝对准确的,而且中间耗时或阻塞错过下一个点,那么下一个点就pass过去了 此份面试题包含40个题目是现在网上能搜索到的一个比较热的一份但是答案并不是很详细和完整基本答案来着cocoaChina和一些自己的补充。 34.Difference between shallow copy and deep copy? 浅复制和深复制的区别 答案浅层复制只复制指向对象的指针而不复制引用对象本身。 深层复制复制引用对象本身。 意思就是说我有个A对象复制一份后得到A_copy对象后对于浅复制来说A和A_copy指向的是同一个内存资源复制的只不过是是一个指针对象本身资源 还是只有一份那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了 两份独立对象本身。 用网上一哥们通俗的话将就是 浅复制好比你和你的影子你完蛋你的影子也完蛋 深复制好比你和你的克隆人你完蛋你的克隆人还活着。 35.What is advantage of categories? What is difference between implementing a category and inheritance? 类别的作用继承和类别在实现中有何区别 答案category 可以在不获悉不改变原来代码的情况下往里面添加新的方法只能添加不能删除修改。 并且如果类别和原来类中的方法产生名称冲突则类别将覆盖原来的方法因为类别具有更高的优先级。 类别主要有3个作用 (1)将类的实现分散到多个不同文件或多个不同框架中。 (2)创建对私有方法的前向引用。 (3)向对象添加非正式协议。 继承可以增加修改或者删除方法并且可以增加属性。 36.Difference between categories and extensions? 类别和类扩展的区别。 答案category和extensions的不同在于后者可以添加属性。另外后者添加的方法是必须要实现的。 extensions可以认为是一个私有的Category。 37.Difference between protocol in objective c and interfaces in java? oc中的协议和java中的接口概念有何不同 答案OC中的代理有2层含义官方定义为 formal和informal protocol。前者和Java接口一样。 informal protocol中的方法属于设计模式考虑范畴不是必须实现的但是如果有实现就会改变类的属性。 其实关于正式协议类别和非正式协议我很早前学习的时候大致看过也写在了学习教程里 “非正式协议概念其实就是类别的另一种表达方式“这里有一些你可能希望实现的方法你可以使用他们更好的完成工作”。 这个意思是这些是可选的。比如我门要一个更好的方法我们就会申明一个这样的类别去实现。然后你在后期可以直接使用这些更好的方法。 这么看总觉得类别这玩意儿有点像协议的可选协议。 现在来看其实protocal已经开始对两者都统一和规范起来操作因为资料中说“非正式协议使用interface修饰“ 现在我们看到协议中两个修饰词“必须实现(requied)”和“可选实现(optional)”。 38.What are KVO and KVC? 答案kvc:键 - 值编码是一种间接访问对象的属性使用字符串来标识属性而不是通过调用存取方法直接或通过实例变量访问的机制。 很多情况下可以简化程序代码。apple文档其实给了一个很好的例子。 kvo:键值观察机制他提供了观察某一属性变化的方法极大的简化了代码。 具体用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控。 比如我自定义的一个button [cpp] [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 { ([keyPath isEqualToString:highlighted] ) { [self setNeedsDisplay]; } } 对于系统是根据keypath去取的到相应的值发生改变理论上来说是和kvc机制的道理是一样的。 对于kvc机制如何通过key寻找到value “当通过KVC调用对象时比如[self valueForKey:”someKey”]时程序会自动试图通过几种不同的方式解析这个调用。首先 查找对象是否带有 someKey 这个方法如果没找到会继续查找对象是否带有someKey这个实例变量iVar如果还没有找到程序会继续 试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话程序会抛出一个 NSUndefinedKeyException异常错误。 (cocoachina.com注Key-Value Coding查找方法的时候不仅仅会查找someKey这个方法还会查找 getsomeKey这个方法前面加一个get或者_someKey以及_getsomeKey这几种形式。同时查找实例变量的时候也会不仅仅查找 someKey这个变量也会查找_someKey这个变量是否存在。 设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时对象能够在错误发生前有最后的机会响应这个请求。这样做有很多好处下面的两个例子说明了这样做的好处。“ 来至cocoa这个说法应该挺有道理。 因为我们知道button却是存在一个highlighted实例变量.因此为何上面我们只是add一个相关的keypath就行了 可以按照kvc查找的逻辑理解就说的过去了。 39.What is purpose of delegates? 代理的作用 答案代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类而不需要获取到那些类的指针。可以减少框架复杂度。 另外一点代理可以理解为java中的回调监听机制的一种类似。 40.What are mutable and immutable types in Objective C? oc中可修改和不可以修改类型。 答案可修改不可修改的集合类。这个我个人简单理解就是可动态添加修改和不可动态添加修改一样。 比如NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的后者可以添加等可以动态申请新的内存空间。 41.When we call objective c is runtime language what does it mean? 我们说的oc是动态运行时语言是什么意思 答案多态。 主要是将数据类型的确定由编译时推迟到了运行时。 这个问题其实浅涉及到两个概念运行时和多态。 简单来说运行时机制使我们直到运行时才去决定一个对象的类别以及调用该类别对象指定方法。 多态不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类life都用有一个相同的方法-eat; 那人类属于生物猪也属于生物都继承了life后实现各自的eat但是调用是我们只需调用各自的eat方法。 也就是不同的对象以自己的方式响应了相同的消息响应了eat这个选择器。 因此也可以说运行时机制是多态的基础~~~ 42.what is difference between NSNotification and protocol? 通知和协议的不同之处 答案协议有控制链(has-a)的关系通知没有。 首先我一开始也不太明白什么叫控制链专业术语了~。但是简单分析下通知和代理的行为模式我们大致可以有自己的理解 简单来说通知的话它可以一对多一条消息可以发送给多个消息接受者。 代理按我们的理解到不是直接说不能一对多比如我们知道的明星经济代理人很多时候一个经济人负责好几个明星的事务。 只是对于不同明星间代理的事物对象都是不一样的一一对应不可能说明天要处理A明星要一个发布会代理人发出处理发布会的消息后别称B的 发布会了。但是通知就不一样他只关心发出通知而不关心多少接收到感兴趣要处理。 因此控制链has-a从英语单词大致可以看出单一拥有和可控制的对应关系。 43.What is push notification? 什么是推送消息 答案太简单不作答~~~~~~~~~~ 这是cocoa上的答案。 其实到不是说太简单只是太泛泛的一个概念的东西。就好比说什么是人。 推送通知更是一种技术。 简单点就是客户端获取资源的一种手段。 普通情况下都是客户端主动的pull。 推送则是服务器端主动push。 44.Polymorphism 关于多态性 答案多态子类指针可以赋值给父类。 这个题目其实可以出到一切面向对象语言中 因此关于多态继承和封装基本最好都有个自我意识的理解也并非一定要把书上资料上写的能背出来。 最重要的是转化成自我理解。 45.Singleton? 对于单例的理解 答案1112题目其实出的有点泛泛的感觉了可能说是编程语言需要或是必备的基础。 基本能用熟悉的语言写出一个单例以及可以运用到的场景或是你编程中碰到过运用的此种模式的框架类等。 进一步点考虑下如何在多线程访问单例时的安全性。 46.What is responder chain? 说说响应链 答案 事件响应链。包括点击事件画面刷新事件等。在视图栈内从上至下或者从下之上传播。 可以说点事件的分发传递以及处理。具体可以去看下touch事件这块。因为问的太抽象化了 严重怀疑题目出到越后面就越笼统。 47.Difference between frame and bounds? frame和bounds有什么不同 答案:frame指的是该view在父view坐标系统中的位置和大小。参照点是父亲的坐标系统 bounds指的是该view在本身坐标系统中 的位置和大小。参照点是本身坐标系统 48.Difference between method and selector? 方法和选择器有何不同 答案selector是一个方法的名字method是一个组合体包含了名字和实现. 详情可以看apple文档。 49.Is there any garbage collection mechanism in Objective C.? OC的垃圾回收机制 答案 OC2.0有Garbage collection但是iOS平台不提供。 一般我们了解的objective-c对于内存管理都是手动操作的但是也有自动释放池。 但是差了大部分资料貌似不要和arc机制搞混就好了。 求更多~~ 50.NSOperation queue? 答案存放NSOperation的集合类。 操作和操作队列基本可以看成java中的线程和线程池的概念。用于处理ios多线程开发的问题。 网上部分资料提到一点是虽然是queue但是却并不是带有队列的概念放入的操作并非是按照严格的先进现出。 这边又有个疑点是对于队列来说先进先出的概念是Afunc添加进队列Bfunc紧跟着也进入队列Afunc先执行这个是必然的 但是Bfunc是等Afunc完全操作完以后B才开始启动并且执行因此队列的概念离乱上有点违背了多线程处理这个概念。 但是转念一想其实可以参考银行的取票和叫号系统。 因此对于A比B先排队取票但是B率先执行完操作我们亦然可以感性认为这还是一个队列。 但是后来看到一票关于这操作队列话题的文章其中有一句提到 “因为两个操作提交的时间间隔很近线程池中的线程谁先启动是不定的。” 瞬间觉得这个queue名字有点忽悠人了还不如pool~ 综合一点我们知道他可以比较大的用处在于可以帮组多线程编程就好了。 51.What is lazy loading? 答案懒汉模式只在用到的时候才去初始化。 也可以理解成延时加载。 我觉得最好也最简单的一个列子就是tableView中图片的加载显示了。 一个延时载避免内存过高一个异步加载避免线程堵塞。 52.Can we use two tableview controllers on one viewcontroller? 是否在一个视图控制器中嵌入两个tableview控制器 答案一个视图控制只提供了一个View视图理论上一个tableViewController也不能放吧 只能说可以嵌入一个tableview视图。当然题目本身也有歧义如果不是我们定性思维认为的UIViewController 而是宏观的表示视图控制者那我们倒是可以把其看成一个视图控制者它可以控制多个视图控制器比如TabbarController 那样的感觉。 53.Can we use one tableview with two different datasources? How you will achieve this? 一个tableView是否可以关联两个不同的数据源你会怎么处理 答案首先我们从代码来看数据源如何关联上的其实是在数据源关联的代理方法里实现的。 因此我们并不关心如何去关联他他怎么关联上方法只是让我返回根据自己的需要去设置如相关的数据源。 因此我觉得可以设置多个数据源啊但是有个问题是你这是想干嘛呢想让列表如何显示不同的数据源分区块显示 转载于:https://www.cnblogs.com/i0ject/p/3933366.html