1.@class @PRoperty (retain) Book *book 假设有两个类,一个是 Card,一个是 Person,当 Card 中包含 Person,我们就需要在 Card 前加上#import “Person.h“。 如果此时 Person 中再包含 Card 的话,我们就又得在 Person 类前加上#import “Card.h”。这时再编译运行就会 出现故障,因为编译运行会导致两个类不停得拷贝对方,导致报错。 这时可以在两个类前用:@class 类 就可以避免这种问题,比如在 Person 中用@class Card;代替#import “Card.h”。在 Card 中用@class Person;代替 import “Person.h”。但是这样还是有一个问题,它仅仅告诉编译器某个名称是一个类,并没有把这个类中的 所有东西拷贝过来。在实际开发中: (1) 在.h 文件中用@class 来声明类 (2) 在.m 文件中用#import 来包含类的所有东西 –@class 和#import 的区别(高频面试题): 对于循环依赖关系来说,比如 A 类引用 B 类,同时 B 类也引用 A 类: 这种代码会报错,当时用@class 在两个类中互相声明,就不会编译报错。 (1)#import 方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class 方式只是告诉编译器在 A.h 文件中 B *b 只是类的声明,具体这个类有什么信息,这里不需要知道,等实现文件中真正要用到时,才会去 查看 B 类中信息。 (2)如果有上百个头文件都#import 了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍 有改动,后面引用这个文件的所有类都要重新编译一遍,这样对效率的影响也是可想而知的。相对来讲,使 用@class 方式就不会出现这种问题了。 (3)在.m 实现文件中,如果需要引用到被引用类的尸体变量或者方法时,还需要使用#import 方式引用被引用 类。
2.循环引用 循环 retain 问题(循环引用问题 1,非 ARC 下发生): 一端用 retain,一端用 assign 循环 strong 问题(循环引用问题 2,ARC 下发生) :一端用 strong,另一端用 weak
3.block代码块 Block 和方法很像,Block 特点: (1)可以保存代码 (2)可以有返回值 (3)可以有形参 (4)调用方式和调用方法一样 (5)可以像方法一样调用外面的变量 (6)默认条件下,Block 不能修改外面的局部变量,但是在变量名前加上_block 就可以使 Block 可以修改这 个变量。比如: _block int b = 20; 但是 Block 可以修改全局变量。 (7)实际开发中,常用 typedef 定义 Block 以减少代码量,比如: typedef int (*MyBlock)(int, int); 以后再定义 Block 就可以: MyBlock sumBlock = ^(int a,intb){ return a + b; } 【备注】当 block 用到外面的东西时候,要把用的的外面的那个东西声明为弱指针,否则会发生循环引用的 问题。声明方法: _weak ViewController *vc = self;//可以避免野指针,推荐使用 或者: _unsafe_unretained ViewController *vc = self; 以后在代码块里调用的 vc 就以弱指针的方式调用。
4.通过代码创建一个控件 关于控件的继承关系(面试重点): (1)所有的控件都继承自 UIView。 (2)能监听事件的都是先继承自 UIControl,UIControl 再继承自 UIView。比如 UIButton。 (3)能整体滑动的都是继承自 UIScrollView,UIScrollView 再继承自 UIView。比如 UITableView。 (4)UIWindow 也是继承自 UIView。 首先,创建控件的代码要写在 - (void)viewDidLoad{ }; 中,这个方法是在 view 被创建完毕后执行的方法。
5.transform transform 是一个状态,并不能改变控件的真实位置(以起始位置为参照,起始位置为(0,0),即真实位置为 (0,0)),如果使用 CGAffineTransformMakeTranslation(0, -100)就会返回控件在真实位置上向上移动 100 像 素后的状态,但真实位置不会改变,当第二次执行 head.transform = CGAffineTransformMakeTranslation (0, -100) 就不会再有变化了,因为控件已经在这个状态了。
6.Plist文件 在创建 Plist 文件的时候要特别注意名称当中不能带“info”,如果带了“info”会导致 xcode 把它误当作一个项 目中某个文件而出现问题。,导致文件加载不进来。
7.UIImage的加载 1、UIImage 的 2 种加载图片方式 (1)有缓存(图片所占用的内存会一直停留在程序中),可能会导致占用大量内存而使程序崩溃,加载少量 小图片时候使用。 + (UIImage )imageNamed:(NSString )name; name 是图片的文件名,png 图片不用加后缀名,jpg 等其他图片格式要加后缀名。 (2)无缓存(图片所占用的内存会在一些特定操作后被清除),在加载大量图片时候使用 + (UIImage )imageWithContentsOfFile:(NSString )path - (id)initWithContentsOfFile:(NSString *)path; path 是图片的全路径 例如: NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:filename ofType:nil]; UIImage *image = [UIImage imageWithContentsOfFile:path];
8.UIapplication UIApplication 对象是应用程序的象征。每一个应用都有自己的 UIApplication 对象,而且是单例(只能有一个对 象,我们不能去创建新对象,只能获取这个对象)的。通过[UIApplication sharedApplication]可以获得这个单例 对象。 一个 iOS 程序启动后创建的第一个对象就是 UIApplication 对象。利用 UIApplication 对象,能进行一些 应用级别的操作。 UIApplication 有个功能十分强大的 openURL:方法 - (BOOL)openURL:(NSURL*)url; openURL:方法的部分功能: (1)打电话 UIApplication *app = [UIApplication sharedApplication]; [app openURL:[NSURL URLWithString:@”tel://10086”]]; (2)发短信 [app openURL:[NSURL URLWithString:@”sms://10086”]]; (3)发邮件 [app openURL:[NSURL URLWithString:@”mailto://12345@QQ.com”]]; (4)打开一个网页资源(自动跳转到浏览器打开)[app openURL:[NSURL URLWithString:@”http://ios.123.cn“]]; (5)打开其他 app 程序 …….
9.UIWindow UIWindow 是一种特殊的 UIView,通常在一个 app 中只会有一个 UIWindow。 iOS 程序启动完毕后,创建的第一个视图控件就是 UIWindow,接着创建控制器的 view,最后将控制器的 view 添加到 UIWindow 上,于是控制器的 view 就显示在屏幕上了。
10.响应者对象 在 iOS 中不是任何对象都能处理事件,只有继承了 UIResponder 的对象才能接收并处理事件。我们称之为“响 应者对象”, UIApplication、UIViewController、UIView 都继承自 UIResponder,因此它们都是响应者对象,都能够接收并处 理事件。
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件(掌握)。
UIView 不接收触摸事件的三种情况: (1)不接收用户交互 userInteractionEnabled = NO (2)隐藏 hidden = YES (3)透明 alpha = 0.0 ~ 0.01 【备注】UIImageView 的 userInteractionEnabled 默认就是 NO,因此 UIImageView 以及它的子控件默认是不能接收触摸事件的。
11. 响应者链的事件传递过程 (1)如果 view 的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图。 (2)在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给 window 对象进行处理。 (3)如果 window 对象也不处理,则其将事件或消息传递给 UIApplication 对象。 (4)如果 UIApplication 也不能处理该事件或消息,则将其丢弃。
12、触摸事件完整处理过程 1、先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理事件。 2、调用最合适控件的 touches…方法。 3、如果这个控件调用了[super touches…];就会将事件顺着相应链条往下传递,传递给下一个响应者。 4、接着就会调用下一个响应者的 touches…方法。 5、事件还可以继续往下传递,直到 UIApplication,如果 UIApplication 也不处理该事件或消息,则将其丢弃。 【备注】关于上面的下一个响应者: (1) 如果当前这个 View 是控制器的 View,那么控制器就是下一个响应者。 (2) 如果当前这个 View 不是控制器的 View,那么父控件就是下一个响应者。
新闻热点
疑难解答