1,请简述你对协议的理解?
protocol无论是在那个领域都是一种约束,规范。在OC中的协议主要用于在各个类之间进行回调传值。 协议有 委托方,代理方, 委托方是协议的制定者,需要声明协议的方法,实现协议的对象。代理方,是协议的遵守着,需要遵守协议,并实现协议中的必要方法。
2,如何理解ARC自动引用计数机制?
Cocoa采用了引用计数(reference
counting)机制,每一个对象有一个关联的“整数retainCount”用于记录对象的使用情况。对象被引用时retaincount+1,外部
环境结束对象的使用后retainCount-1.当retaincount为0的时候,该对象被销毁。
当我们使用alloc、new或者copy的我们需要销毁这个对象。release函数,只是将对象的retainCount值减1,并不是删除对象。当retainCount==0的时候,系统会发给对象一个dealloc消息,另外:千万不要手动调用dealloc,因为我们不知道何时,何地,何人还会使用该对象。应该老老实实依赖引用计数机制完成内存管理。
释放对象所有权的函数除了release还有autorelease,这是一种延迟操作。
3,如何理解 retain/copy/assign/release/autor release/dealloc关键字?
copy:建立一个索引计数为1的对象,然后释放旧对象,主要用于nsstring;
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
对其他NSObject和其子类
assign: 简单赋值,不更改索引计数
release:手动释放对象;
dealloc:它的作用是,当对象的引用计数为0,系统会自动调用dealloc方法,回收内存。
autorelease 原理:
a.先建立一个autorelease pool
b.对象从这个autorelease pool里面生成。
c.对象生成 之后调用autorelease函数,这个函数的作用仅仅是在autorelease pool中做个标记,让pool记得将来release一下这个对象。
d.程序结束时,pool本身也需要rerlease, 此时pool会把每一个标记为autorelease的对象release一次。如果某个对象此时retain count大于1,这个对象还是没有被销毁。
(weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放 ,即使还有weak型指针指向它。weak表示如果还没有人指向它了,它就会被清除内存,同时被指向nil
4 self.name与_name的区别
1.首先通过self.xxx 通过访问的方法的引用:包含了set和get方法。而通过下划线是获取自己的实例变量,不包含set和get的方法。
2.self.xxx是对属性的访问;而xxx是对局部变量的访问。所有被声明为属性的成员,再ios5之前需要使用编译指令@synthesize 来告诉编译器帮助生成属性的getter和setter方法,之后这个指令可以不用认为的指定了,默认情况下编译器会帮助我们生成。编译器在生成getter,setter方法时是有优先级的,他首先查找当前的类中用户是否定义属性的getter,setter方法,如果有,则编译器会跳过,不会再生成,使用用户定义的方法。也就是说你在使用self.xxx时是调用一个getter方法。会使引用计数加一,而xxx不会使用引用技术加一的。
所有使用self.xxx是更好的选择,因为这样可以兼容懒加载,同时也避免了使用下滑线的时候忽略了self这个指针,后者容易在BLock中造成循环引用。同时,使用 _是获取不到父类的属性,因为它只是对局部变量的访问。
最后总结:self方法实际上是用了get和set方法间接调用,下划线方法是直接对变量操作。
5 继承 与 类别 的联系与区别
联系:
可以给一个类扩展新的方法,或修改已有的方法
区别:
1. 继承修改的方法不会对父类原方法产生影响;类别修改的方法相当于替换了原有方法
2. 以viewController举例,继承一个viewController相当于建立一个新的页面;而给一个viewController添加类别用于增加或修改原viewController上的方法
3. 类别支持开发人员针对自己构建的类,把相关的方法分组到多个单独的文件中,对于大型而复杂的类,这有助于提高可维护性,并简化单个源文件的管理。
4. 针对系统提供的一些类,例如:NSString,NSArray,NSNumber等类,系统本身不提倡使用继承去扩展方法,因为这些类内部实现对继承有所限制,所以最后使用类别来进行方法扩展。
5. 理论上类别不能新增属性
6 Strong与Weak的区别
(weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会被释放 ,即使还有weak型指针指向它。 一旦最后一个strong型指针离去 ,这个对象将被释放,所有剩余的weak型指针都将被清除。 可能有个例子形容是妥当的。 想象我们的对象是一条狗,狗想要跑掉(被释放)。 strong型指针就像是栓住的狗。只要你用牵绳挂住狗,狗就不会跑掉。如果有5个人牵着一条狗(5个strong型指针指向1个对象),除非5个牵绳都脱落 ,否着狗是不会跑掉的。 weak型指针就像是一个小孩指着狗喊到:“看!一只狗在那” 只要狗一直被栓着,小孩就能看到狗,(weak指针)会一直指向它。只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。
只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。
///////////////////////////////////////////////////////////////////////////////////////////////
100.私有api与 公开api的区别
iPhone中的API除了公开的API:Published API外(或者叫文档中记录的API:Documented API),还有两类API:私有API:Private API和未公开的API:UnPublished API(或者叫文档中未记录的API:Undocumented API)。其中私有API是指放在PrivateFrameworks框架中的API,未公开的API是指虽然放在Frameworks框架中,但是却没 有在苹果的官方文档中有使用说明、代码介绍等记录的API。后两种API是有区别的,按苹果的说法,未公开的API是还不够成熟,可能还会变动的API, 等完全成型了后会变成公开的API,但是目前不对其提供承诺,就是系统版本升级后可能会失效。而私有API是苹果明确不能使用的API。虽然两者有所区 别,但是在具体使用方法上是类似的。
如何理解 动画
7:assign是指针赋值,不对引用计数操作,使用之后如果没有置为nil,可能就会产生野指针;而weak一旦不进行使用后,永远不会使用了,就不会产生野指针
8:1)尝试使用Xcode的转换工具
2)在编译选项中,为MRC的程序添加-fno-objc-arc标记,表明在编译时,该文件用用MRC编译
3)讲MRC的第三方库直接编译成静态库使用
9:Object-c中没有多继承,Cocoa中所有的类都是NSObject的子类,多继承在这里是用protocl委托代理来实现的
10:objective c中既有私有方法,也有私有变量。
先说私有方法,
由于Objective-C的动态消息传递机制,OC中不存在真正意义上的私有方法。
但是如果你不在.h文件中声明,只在.m文件中实现,或在.m文件的Class Extension里声明,那么基本上和私有方法差不多。
至于私有变量是可以通过@private来声明的,例如:
@interface Sample : NSObject{
@private
NSString *tteesstt;
}
@property (nonatomic,strong) NSString *hoge;
- (void)foo;
@end
则tteesstt变量是私有的。而属性hoge是默认公有。
现在Apple官方文档里是用property比较多,直接定义instance variable(实例变量)少。将property定义到.m的Class Extension(类扩展)也基本上和私有变量差不多。
简而言之,将你希望公有的放到.h文件,私有的放到.m文件。在import时只import .h文件(.m文件也是可以import的,但是我们一般不这么做)。
11、#import"".h和@class+类名的区别
1.import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。
2.在头文件中, 一般只需要知道被引用的类的名称就可以了。 不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
3.在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。
4.如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系,如果使用#import来相互包含,那么就会出现编译错误,如果使用@class在两个类的头文件中相互声明,则不会有编译错误出现。
所以,一般来说,@class是放在interface中的,只是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,如果需要引用这个类的实体变量或者方法之类的,还是需要import在@class中声明的类进来.
12、请简述页面传值都有哪些实现方式
代理、block、通知、属性传值、单例传值、NSUserDefault
13、请简述深拷贝和浅拷贝的区别
浅拷贝只复制对象的本身,对象里的属性、包含的对象不做复制,源对象和副本指向的是同一个对象,对象的引用计数器+1,其实相当于做了一次retain操作
深拷贝则复制对象本身,对象的属性也会复制一份。源对象和副本指向的是不同的两个对象,源对象引用计数器不变,副本计数器设置为1
只有不可变对象创建不可变副本才是浅拷贝,其他都是深拷贝
14、系统中有哪些对象是单例
UIApplication(应用程序实例)
NSNotificationCenter(消息中心):
NSFileManager(文件管理):
NSUserDefaults(应用程序设置):
NSURLCache(请求缓存):
NSHTTPCookieStorage(应用程序cookies池):
15、请简述你对MVC设计模式的理解
使用了MVC的应用程序被分为3个核心部件:视图(View)、模型(Model)、控制器(Controller)。他们各司其职,既分工明确又相互合作。
Model:持有我们应用程序的数据,和定义怎么操纵它、
View:处理用户的操作和展示Model
Controller:它的作用是协调View和Model把数据展示到View上
Controller可以直接和Model通信,也可以直接和View通信。Model和View永远不能直接通信
16、iOS中哪些技术符合观察者模式
在iOS开发中,会接触到的经典观察者模式的实现方法有NSNotificationCenter,KVO,Delegate等
17、什么是工厂方法?在基类中定义创建对象的一个接口,让子类决定实例化那个类,工厂方法让一个类的实例化延迟到子类中进行。工厂方法要解决的问题的对象的创建 时机,它提供了一种拓展的策略,很好的符合了开放封闭原则,工厂方法也叫作虚构造器。
18、什么是代理模式,实现代理需要注意什么
在项目中我们经常会用到代理的设计模式,这是ios的一种消息传递方式,也可以通过这种方式来传递一些参数,ios中对代理支持的很好,有代理对象、委托者、协议三部分组成。
协议:用来指定代理双方可以做什么,必须做什么;
代理:根据指定的协议,完成委托方需要实现的功能;
委托:根据指定的协议,指定代理去完成什么功能
19 、请简述StoryBoard和Xib的联系和区别
联系:
都用来描述软件界面
都用Interface Builder工具来编辑
区别:
Xib是轻量级的,用来描述局部的UI界面
Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
20、请简述UITableView对Cell的重用机制
UITableView维护了一个复用队列,当Cell从屏幕上消失时,就会进入复用队列。下一个Cell要显示的时候通过复用id查询在复用队列是否有同一类型的Cell,若有取出来复用,若没有就会重新创建一个Cell。重用机制通过对Cell的重复使用,来减少内存的使用。
21 、如何用UIScrollView实现无限加载多张图片
创建一个UIScrollView,高度为屏幕的高度,宽度为三倍的屏幕宽度,设置为按屏幕滑动,设置偏移量(屏幕宽度,0)。第一个屏幕宽度和第三个屏幕宽度贴一个UIImageView显示图片的前一张和后一张,中间贴一个UIScrollView,大小为屏幕的大小,在上面贴一个UIImageView显示要显示的图片。当向左滑动,通过UIScrollView的代理方法,检测到之后将第一个屏幕宽度和第三个屏幕宽度上的UIImageView改为图片的前一张和后一张,中间scrollview上的UIImageView上的图片改为当前图片,同时设置最外部的UIScrollView的偏移量为(屏幕宽度,0);向右滑动与向左滑动同理。
22、请简述视图控制器的生命周期
1、alloc 创建对象,分配空间
2、init 初始化对象
3、loadView 从xib中载入视图
4、viewDidLoad 载入完成,可以自定义数据和控件了
5、viewWillAppear 视图将要出现在屏幕上之前
6、viewDidAppear 视图已经出现在屏幕上
7、viewWillDisappear 视图将要消失
8、viewDidDisappear 视图已经消失
9、销毁
23 、UITableView有哪些优化方式
1、 提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法;
2、异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口;
3、滑动时按需加载,这个在大量图片展示,网络加载的时候很管用
4、Cell的复用
5、尽量少使用或者不用透明的图层
6、用异步加载数据,缓存请求结果
7、减少subView的数量
8、异步刷新
9、提前注册
24 、请简述iOS中的事件传递机制
点击一个UIView或产生一个触摸事件A,这个触摸事件A会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。
UIApplication会从事件对列中取出最前面的事件(此处假设为触摸事件A),把事件A传递给应用程序的主窗口(keyWindow)。
窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。
事件交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应链向上传递,交给下一个响应者,直到事件被丢弃
25 、UITableView中有哪些必须要实现的数据源的方法
1、每组的行数 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
2、每行的cell -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
26 、请简述Http协议中get请求和post请求的区别
get和post的主要区别表现在数据传递上
get: 1、在请求url后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开,比如http://www.test.com/login?username=123&pwd=234&type=JSON
2、由于浏览器和服务器对URL长度有限制,因此在URL后面附带的参数是限制的,通常不能超过1kb
post:1、发给服务器的参数全部放在请求体中
2、理论上,POST传递的数据量没有限制(具体还得看服务器的处理能力)
选择:1)、如果要传递大量数据,比如文件上传,只能用post请求
2).get的安全性比post要差些,如果包含机密\敏感信息,建议用post
3).如果仅仅是索取数据(数据查询),建议用get
4).如果是增加、修改、删除数据,建议使用post
27 、请简述你对异步请求数据的理解
异步请求:通过两个线程调用服务,一个线程发送,一个线程接受
请求行为在后台,不会导致页面假死
28.iOS中哪些技术可以实现开辟线程,他们之间的联系和区别是什么?
答:创建方式:
NSThread,NSOperation,GCD。
联系:
三种编程方式都是针对线程操作来讲的,从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单
区别:
•NSThread:
–优点:NSThread 比其他两个轻量级,使用简单
–缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销
•NSOperation:
–不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上
–NSOperation是面向对象的,基于OC语言实现的API。两种默认实现:NSInvocationOperation 和 NSBlockOperation。
•GCD:
–Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和强大的技术
–GCD是基于C语言的API,提供了非常多强大的函数。GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)。程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码。我们在编写GCD相关代码的时候,面对的函数,而不是方法。GCD中的函数大多数都以dispatch开头。
29.NThread中线程是如何进行通信的?
???????????????????????????? 答:线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信
线程间通信的体现
1个线程传递数据给另1个线程
在1个线程中执行完特定任务后,转到另1个线程继续执行任务
线程间通信常用方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
举例下载图片
// 在子线程中调用download方法下载图片
[self performSelectorInBackground:@selector(download) withObject:nil];
-(void)download
{…//图片下载完成
//2.回到主线程中设置图片
//第一种方式
// [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
//第二种方式
// [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
//第三种方式
[self.iconView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
}
GCD的线程通信
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执?耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执?UI刷新操作
});
});
30.GCD中有哪些创建线程的方式
GCD全称 Grand Central Dispatch,可称为大中央调度。实际上GCD是管理着一个线程池,如何创建线程,如何回收线程,以及分配多少个线程,这些都是GCD来控制的。 在开发中,程序员是不用操作线程的相关事情,程序员只需要把应该做的 操作 放到相应的 队列 里面即可。
在 GCD 中,加入了两个非常重要的概念: 任务 和 队列。
任务:即操作,GCD 中就是一个 Block。任务有两种执行方式: 同步执行 和 异步执行。
同步(sync) 和 异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕!
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。
队列:用于存放任务。一共有两种队列, 串行队列 和 并行队列。
串行队列 中的任务会根据队列的定义 FIFO 的执行,一个接一个的先进先出的进行执行。
并行队列的任务,GCD 也会 FIFO的取出来,但不同的是,它取出来一个就会放到别的线程,然后再取出来一个又放到另一个的线程。
队列与线程管理:
三大队列介绍种类:
一、主线程的Main queue,通过dispatch_get_main_queue获取。
二、并行队列global dispatch queue,通过dispatch_get_global_queue获取,由系统创建(不需要开发人员去创建)三个不同优先级的dispatch queue。并行队列的执行顺序与其加入队列的顺序相同。
三、串行队列serial queues一般用于按顺序同步访问,可创建任意数量的串行队列,各个串行队列之间是并发的。一般用dispatch_queue_create来进行创 建,非arc的情况下需要用户手动来释放队列,可能会有人说,既然队列也是一种对象,可以创建和释放,那一定会有引用计数器了,是的,可以使用函数 dispatch_retain和dispatch_release来增加或者减少引用计数器。
两种提交 job的方式:dispatch_async和dispatch_sync,分别是异步执行和同步执行,两者之前的区别在于,前者在把任务提交到队列执行 不会造成阻塞,而后者后面的代码块需要等到队列中的任务执行完成后才可以执行。
1. //主线程异步执行
dispatch_async(dispatch_get_main_queue(), ^{ 。。。});
3. //主线程同步执行
dispatch_sync(dispatch_get_main_queue(), ^{。。。});
31,iOS中有哪些技术可以保证线程安全
增加互斥锁。有效防止因多线程抢夺资源造成的安全问题。线程同步,多条线程按顺序地执行任务。hu互斥锁,就是使用了线程同步技术。
atomic加锁。
32,ASIHttpRequest的父类是什么
NSOperation
33,请简述AFNetWorking的实现原理
全称是AFNetworking
虽然运行效率没有ASI高,但是使用比ASI简单
是对NSURLConnection和NSURLSession的各自的一层包装
AFN的内部中的RunLoop
AFN内部开了一条专门用来访问网络请求的线程
在这个开线程的方法中,他把方法和dispatch_once都用static修饰了下
以保证这个方法的安全性以及只开辟一块内存空间,而且保证他线程不死
在这个方法中他会调用另一个网络请求入口的方法
在这个入口方法中他会创建一个RunLoop
然后添加一个NSMachPort端口,目的是为了让他里面有Source(因为有了Source的RunLoop才能真正跑起来)
然后启动RunLoop,通过RunLoop在里面不断的循环,不断的发送消息,让他做事情.
34.你如何理解Block,Block有什么用途
block是对象,它封装了一段代码,这段代码可以在任何时候执行。
block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:block是inline的,并且它对局部变量是只读的。
35.请简述TCP和UDP的区别
TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!
区别
是否连接 :面向连接 面向非连接
传输可靠性:可靠 不可靠
应用场合 :传输大量数据 少量数据
速度 :慢 快
36.请问怎样保证定位更省电
开启API并获取到位置信息后,就手动stop()。
37 、请简述SDWebImage的实现原理
SDWebImage 中为 UIView 提供了一个分类叫做 WebCache, 这个分类中有一个最常用的接口,sd_setImageWithURL:placeholderImage:, 这个分类同时提供了很多类似的方法, 这些方法最终会调用一个同时具有 optionprogressBlock completionBlock 的方法, 而在这个类最终被调用的方法首先会检查是否传入了 placeholderImage 以及对应的参数, 并设置 placeholderImage.
然后会获取 SDWebImageManager 中的单例调用一个 downloadImageWithURL:... 的方法来获取图片, 而这个 manager 获取图片的过程有大体上分为两部分, 它首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以 url 作为数据的索引先在内存中寻找是否有对应的缓存, 如果缓存未命中就会在磁盘中利用 MD5 处理过的 key 来继续查询对应的数据, 如果找到了, 就会把磁盘中的缓存备份到内存中.
然而, 假设我们在内存和磁盘缓存中都没有命中, 那么 manager 就会调用它持有的一个 SDWebImageDownloader 对象的方法downloadImageWithURL:... 来下载图片, 这个方法会在执行的过程中调用另一个方法addProgressCallback:andCompletedBlock:forURL:createCallback: 来存储下载过程中和下载完成的回调, 当回调块是第一次添加的时候, 方法会实例化一个 NSMutableURLRequest 和 SDWebImageDownloaderOperation, 并将后者加入 downloader 持有的下载队列开始图片的异步下载.
而在图片下载完成之后, 就会在主线程设置 image 属性, 完成整个图像的异步下载和配置.
38、请简述xml和json数据各有什么优势
XML 更适合数据定义,数据存储。它对数据的表达使得这个数据脱离你程序的上下文仍然存在意义并且可以被解读。所以 XML 适合作为配置文件,以及数据存储,存盘文件格式等等。
JSON 更适合数据传输。JSON数据体积相对于XML小,对于传输而言,双方必然需要遵循协商好的协议,因而 JSON 对数据的表达并不需要在数据传输的双方以外仍然具有可解读的意义,只要传输的双方能读懂即可。
39、请简述线程和进程有什么联系和区别
定义:进程是系统进行资源分配和调度的一个独立单位;
线程是进程的实体,是cpu调度和分派的基本单位
关系:一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间 可以并发执行。
区别:1)简而言之,一个程序至少有一个进程,一个进程至少有一个线程
2)线程的划分尺度小于进程,使得多线程程序的并发性高
3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存, 从而极大的提高了程序的运行效率
4)线程不能独立执行,必须依存于应用程序中,由应用程序提供多个 线程执行控制
5)多线程的意义在于一个应用程序中,有多个执行部分可以同时执 行。但操作系统不会将多线程看做多个应用,来实现进程的调度和管 理及资源分配。
40、请简述NSUserDefaults的使用场景和使用注意事项
NSUserDefaults支持的数据类型有:NSNumber(NSInteger.float.double),NSString,NSDate,NSArray,NSDictionary,BOOL,如果你想存储其他类 型的对象,你要将其归档并创建一个NSData来实现存储。如需数据永久保存到NSUserDefaults,只需要简单的储存成键值对,注意保存时的key的唯一性,如对相同key赋值则会覆盖以前的数据。
41、iOS中数据库使用什么技术实现的
sqlite和CoreData
常用数据库: SQLServer 2000-----保存游戏的所有用户的信息
Oracle
mysql------网上php网站使用较多
特点: 网络数据库, 支持的功能多, 程序比较大
移动开发常用: sqlite数据库
特点: 足够小, 足够快(本地数据库), 使用比较简单
常用软件: MesaSQlite数据库操作软件
数据库操作语言: SQL(结构化查询语言)
常用开源库: FMDB
CoreData是iOS开发中经常使用的数据持久化的技术。但其操作过程稍微繁琐,即使你只是实现简单的存取,不涉及请求优化,也要进行许多配置工作,代码量在动辄几十行,对新手来说也需要较大时间成本。
MagicalRecord是OC的一个库,协助方便CoreData的工作。其吸收了Ruby on Rails的Active Record模式,目标是:
简化Core Data相关代码
允许清晰,简单,单行获取
当需要优化请求的时候,仍然允许修改NSFetchRequest
安装
1、在 github 上下载MagicalRecord
2、下载完成,将MagicalRecord 文件夹拖到Xcode中,添加进项目。添加CoreData framework。
3、在PCH文件中添加 CoreData+MagicalRecord.h
4、Option: 如果你在使用MagicalRecord方法的时候不想带MR_ 前缀,e.g. 直接用findAll 代替 MR_findAll,就在PCH中在CoreData+MagicalRecord.h之前增加 #defin MR_SHORTHAND 即可。
环境需求
MagicalRecord 需要的环境:
iOS 5.x 及以上, Mac OS 10.7及以上
ARC
iOS4,无ARC ,可以使用兼容版本,1.8.3
用法
创建Model
创建一个Model.xcdatamodeld ,添加一个Person Entity,添加age firstname lastname 三个属性。最后使用Editor > Create NSManagedObject Subclass ORM生成Person类。
初始化
在AppDelegate中:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[MagicalRecord setupCoreDataStackWithStoreNamed:@"Model.sqlite"];
// ...
return YES;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
[MagicalRecord cleanUp];
}
这样就搞定初始化啦!!
增
Person *person = [Person MR_createEntity];
person.firstname = @"Frank";
person.lastname = @"Zhang";
person.age = @26;
[[NSManagedObjectContext MR_defaultContext] MR_save];
查
//查找数据库中的所有Person。
NSArray *persons = [Person MR_findAll];
//查找所有的Person并按照first name排序。
NSArray *personsSorted = [Person MR_findAllSortedBy:@"firstname" ascending:YES];
//查找所有age属性为25的Person记录。
NSArray *personsAgeEuqals25 = [Person MR_findByAttribute:@"age" withValue:[NSNumber numberWithInt:25]];
//查找数据库中的第一条记录
Person *person = [Person MR_findFirst];
改
Person *person = ...;//此处略
person.lastname = object;
[[NSManagedObjectContext MR_defaultContext] MR_save];
删
Person *person = ...;//此处略
[person MR_deleteEntity];
[[NSManagedObjectContext MR_defaultContext] MR_save];
more
MagicalRecord 官方
Magical Record入门教程
Using CoreData with MagicalRecord
Magical Record: how to make programming with Core Data pleasant
来自:http://www.cnblogs.com/mybkn/p/3328183.html
42,请简述什么是主键、什么是外键
主关键字是表中的一个或多个字段,它的值用于唯一地标识表中的某一条记录。主关键字是被挑选出来,主关键字 作表的行的唯一标识的候选关键字。
如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。
43,iOS中如何实现数据模型的存储
(1) 用户默认设置 – 这种情况通常不需要用户干预,如游戏通关信息,Video
播放记录,或者 App 退出之后,下次进入时,希望恢复到退出时的情况。
(2) 设置束(Settings Bundle)-- 提供了一个通过 iPhone、iPad的设置
(Settings)应用程序进行配置的接口。
(3) 直接访问文件系统 – 读写属于当前 App 的 iOS 文件系统部分的文件。
(4) SQLite 数据库 -- 是嵌入式的和轻量级的 SQL 数据库,SQLite 是由 C实现的。
(5) 远端数据库 – 这个一般由 App 调用远端的 RESTFul WCF 服务,将JSON
或者 XML 数据传递给远端的 Web 服务,读写数据库的逻辑完全在 Web 服 务端实现。比如,用户在iPhone/iPad 终端 App 提交了订单,订单数据当然需要写入远端 SQL Server 或Oracle 数据库
44,请简述iOS的沙盒机制
出于安全的目的,应用程序只能将自己的数据和偏好设置写入到几个特定的位置上。当应用程序被安装到设备上时,系统会为其创建一个家目录,这个家目录就是应用程序的沙盒。
45,如何实现真机调试
准备工作:
• 一个苹果开发者账号
• 一个应用ID,对应你想要调试的项目,注意申请App ID时填写bundle identifier必须与你的项目中的bundle identifier完全对应
• 一台iOS设备,其操作系统版本要与你使用的SDK版本相匹配
第一步:获取设备ID
打开你的项目,然后将设备接入到你的开发机中,打开organizer,在Device tab页下可以看到你刚刚接入的设备
第二部:添加设备
打开开发者中心的设备管理页面,点击Add Devices 按钮,将刚刚粘贴的设备ID输入,并为此设备命名,注意,每一个个人开发者账号最多只能添加一百台设备
第三部:生成Provisioning File
同样在开发者中心,点击Provision File管理界面,点击New Profile按钮,为Provisioning file命名,选择我们要调试的APP Id, 并将我们想要进行调试的设备,这里的设备可以多选。点击Submmit,过一段时间后就会,pending状态的Provsioning file 变成Active状态,便可以下载了。
第四步,导入Provisioning File
双击Provisioning File导入,此时会弹出Organizer,并显示所有的已经导入的Provisioning File,如果导入的Provisioning File有效,那么其后的图标会显示为绿色。导入成功后,在Organizer-> device中找到我们添加的设备,点击“Delopyment for XXX”按钮,中途会出现若干对话框输入证书对应的密码,取消即可,至此,设备的设置已经完成,如果正常,设备名后的灯状标示会编程绿色。
第五步:代码签名与运行
点击项目名,在出现的界面中会分别看到Projects和Targets两个tab 页。分别点击Project与Targets,将Build Setting-》Code Signing中的Debug部分签名由Don‘t Sigining设为我们导入的Provisioning File代表的选项。注意Projects与Targets连个都要设置。将运行设备设为我们刚刚添加的设备,Command + R,程序就可以在设备上运行。
后记:常见问题
整个过程中比较容易出的问题有:
• 生成Provisioning File 是没有添加正确的设备,注意所有需要调试的设备都要勾选
• 代码没有选择签名,或选择了错误的签名选项,或只对Project或Targets中的一个进行了签名设置
• 真机调试需要的Provisioning File要为Development版本的(默认),如果只有Distribution版本的是无法调试的
46、如何查找项目中的内存泄露
1.静态分析
通过静态分析我们可以最初步的了解到代码的一些不规范的地方或者是存在的内存泄漏,这是我们第一步对内存泄漏的检测。当然有一些警告并不是我们关心的可以略过。
2.通过instruments来检查内存泄漏
这个方法能粗略的定位我们在哪里发生了内存泄漏。方法是完成一个循环操作,如果内存增长为0就证明我们程序在该次循环操作中不存在内存泄漏,如果内存增长不为0那证明有可能存在内存泄漏,当然具体问题需要具体分析。
3.代码测试内存泄漏
在做这项工作之前我们要注意一下,在dealloc的方法中我们是否已经释放了该对象所拥有的所有对象。观察对象的生成和销毁是否配对。准确的说就是init(创建对象的方法)和dealloc是否会被成对触发(简单说来就是走一次创建对象就有走一次dealloc该对象)。
47、项目中的支付环节如何实现的
这里以支付宝为例:
1.与支付宝进行去签约,获得商户ID(partner)和账号ID(seller)
2.下载响应的公钥、私钥(加密签名用)
3.下载支付宝SDK
4.生成订单信息
5.调用支付宝客户端,用支付宝客户端跟支付宝安全服务区打交道
6.支付完毕返回支付结果给客户端和服务器
48 如何实现项目上线到AppStore
第一步购买Apple开发者账号,使用账号登陆Apple官网,创建证书 下载证书,创建CSR文件,第二步 登陆https://itunesconnect.apple.com 创建应用程序信息,第三步打开你要上线的项目的工程文件 选中X-code 里的product->Archive。 打包你要上线的项目,然后等待苹果公司审核,审核成功就能上线。
49 请简述你在项目中遇到过哪些问题,如何解决的
遇到过很多的问题,比如1第三方库崩溃,解决办法,首先查出哪个第三方库崩溃,可以去github 上重新下载这个更新后的第三方库。2有些项目经理需要你做出来的功能你不能实现,解决办法:换一种思路去实现或者和项目经理沟通看有没有其他可以代替这个功能而且你能做出来的或者去百度去github 上问问别人,总之一定要解决。。3Api问题,可以找服务器端的工作人员商量,可以自己下载别的第三方库来解析这个Api。
50.请简述你理解的内存管理。
创建对象并使用后需要释放,否则会出现内存泄露。
内存管理分为手动内存管理MRC和自动内存管理ARC,
在手动内存管理机制下,如果使用alloc,copy(MutableCopy),retain一个对象时,在使用完毕需要向该对象发送release,或者autorelease消息来释放这个对象,其他方法创建的对象不需要管理内存。
在自动内存管理机制下,系统维护的自动释放池会自动处理。
51、如何实现流媒体格式的视频边播放,边缓存?
1.需要在视频播放器和服务器之间添加一层类似代理的机制,视频播放器不再直接访问服务器,而是访问代理对象,代理对象去访问服务器获得数据,之后返回给视频播放器,同时代理对象根据一定的策略缓存数据。
2.AVURLAsset中的resourceLoader可以实现这个机制,resourceLoader的delegate就是上述的代理对象。
3.视频播放器在开始播放之前首先检测是本地cache中是否有此视频,如果没有才通过代理获得数据,如果有,则直接播放本地cache中的视频即可。
52.请简述你理解的面向对象思想。
(网络简述)
面向对象思想把整个世界看成由各种对象来组成的. 这些对象具有属性和行为, OC中称之为属性和方法. 从最简单的整数到复杂的飞机等均可看作对象, 它不仅能表示具体的事物, 还能表示抽象的规则, 计划或事件.
面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算是一种计算机编程范式, 它将对象作为问题空间的基本元素, 利用对象和对象之间的相互作用来设计程序.
(课件解释)
1、对象是接收命令的基本单位,每个对象负责处理数据的某个方面,多个对象分工合作以完成复杂的功能。
2、生活逻辑的映射
53、如何设计一个缓存类?
1、设计一个CacheItem类,用来请求一个web连接,它的一个实例表示一个缓存项。这个CacheItem类,需要一个url创建一个NSURLConnection,去请求web资源。使用CacheItem类主要用来请求web资源。
2、在NSURLConnection开始请求之前,调用CachedDownloadManager类,来搜索和管理本地的缓存文件。将缓存文件的情况保存到一个字典类中。
3、如果这个文件已经被下载,而且没有过期,则从本地获取文件的数据。如果文件已经过期,则重新下载。我们通过download:urlMustExpireInSeconds:updateExpiryDateIfInCache方法来实现,
详情参考http://w11h22j33.iteye.com/blog/1420733
54—谈谈对蓝牙技术的理解
蓝牙是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换。主从关系
蓝牙技术规定每一对设备之间进行蓝牙通讯时,必须一个为主角色,另一为从角色,才能进行通信,通信时,必须由主端进行查找,发起配对,建链成功后,双方即可收发数据。
55—iOS8.0有什么新特征
1、支持第三方键盘 2、自带网页翻译功能(即在线翻译) 3、指纹识别功能开放:第三方软件可以调用 4、Safari浏览器可直接添加新的插件。 5、可以把一个网页上的所有图片打包分享到Pinterest、 6、支持第三方输入法:将是否授权输入法的选择留給用户 7、Home Kit智能家居 :可以利用iPhone对家居,如灯光等进行控制 8、3D图像应用Metal:可以更充分利用CPU和GPU的性能 9、引入全新基于C语言的编程语言Swift:更快、更安全、更好的交互、更现代 10、 Xcode更新 11、相机和照片API也实现开放
56—懒加载
1.懒加载基本
懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小)。所谓懒加载,写的是其get方法.
注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化
2.使用懒加载的好处:
(1)不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强
(2)每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合
57— 在ARC下发生内存泄露的解决方案
1,循环参照
A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释
解决方案 把其中一个属性的strong改为assign即可。
2,死循环
如果某个ViewController中有无限循环,也会导致即使ViewController对应的view关掉了,ViewController也不能被释放。
这种问题常发生于animation处理。
解决办法 在ViewController关掉的时候,停止这个animation。
-(void)viewWillDisappear:(BOOL)animated {
[self.view.layer removeAllAnimations];
}
3、当一个对象存入到集合中的时候,默认会保存它的强指针,如果最后不对这个集合进行清空操作,一样会有内存溢出的情况
Person * p = [[Person alloc] init];
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr addObject:p];
把对象从集合中移除的时候,也会释放掉这个对象的强指针
[arr removeObject:p];
或者[arr removeAllObjects];
而接下来才是重点:
arr = nil;//如果不进行赋值为nil的操作,一样存在内存溢出的现象,赋值为nil系统会对其进行清空所有强指针的操作.
p = nil;
解决方案 1、建议你找到泄露的那个对象,将其赋值为nil,因为ARC里面,一旦对象没有指针指向,就会马上被释放。
58 —GCD(异步Block中的self.的处理)
用__weak把self重新引用一下就行了 ,像这样:
__weak ViewController *weakSelf = self;
59- APNS 推送的实现过程
首先应用发送通知,系统弹出提示框询问客户是否允许,当用户允许后像苹果服务器(APNS)请求deviceToken,并由苹果服务器发送给自己的应用,自己的应用将DeviceToken发送给自己的服务器,自己的服务器想要发送网络推送时将deviceToken以及想要推送的信息发送给苹果服务器,苹果服务器将信息发送给应用.
60—添加NSNotificationCenter监听,其后面的object的意义是什么?
用NSNotificationCenter添加监听者,其后面的object的意义是:监听同一条通知的多个观察者,在通知到达时,他们执行回调的顺序是不确定的,所以我们不能去假设操作的执行会按照添加观察者的顺序来执行.
61、iOS的加密方式以及优劣
1,MD5加密是最常用的加密方法之一,是从一段字符串中通过相应特征生成一段32位的数字字母混合码。MD5主要特点是 不可逆
2,在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
base64编码后的数据比原始数据略长,为原来的4/3
RSA非对称加密算法 非对称加密算法需要两个密钥非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快 对称密码体制中只有一种密钥,并且是非公开的
62、论Socket和http协议的区别
HTTP:超文本传输协议,首先它是一个协议,并且是基于TCP/IP协议基础之上的应用层协议。TCP/IP协议是传输层协议,主要解决数据如何在网络中传输。HTTP是基于请求-响应形式并且是短连接,并且是无状态的协议
Socket:Socket 不属于协议范畴,而是一个调用接口(API),
Socket是对TCP/IP协议的封装,通过调用Socket,才能使用TCP/IP协议。Socket 连接是长连接,理论上客户端和服务器端一旦建立连接将不会主动断开此连接。Socket连接属于请求-响应形式,服务端可主动将消息推送给客户端
63、 kvo/kvc之间的关系
KVC 与 KVO 是 Objective C 的关键概念。KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值。比如:
[p valueForKeyPath:@"spouse.name"];
相当于这样……
[[p valueForKey:@"spouse"] valueForKey:@"name"];
Key-Value Observing (KVO) 建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。举个例子,用代码观察一个 person 对象的 address 变化,以下是实现的三个方法:
• watchPersonForChangeOfAddress: 实现观察
• observeValueForKeyPath:ofObject:change:context: 在被观察的 key path 的值变化时调用。
• dealloc 停止观察
它通过 key path 观察对象的值,当值发生变化的时候会收到通知。
64、数据持久化机制
1.属性列表
2.对象归档
3.数据库存储(SQLite3)
4.苹果公司提供的持久性工具Core Data。
① 属性列表文件是一种XML文件,Foundation框架中的数组和字典等都可以于属性列表文件相互转换。
NSArray类常用读写属性列表文件的方法:+arrayWithContentsOfFile;-initWithContentsOfFile ;-writeToFile:atomically。
NSDictionary类常用读写属性列表文件的方法:+dictionaryWithContentsOfFile;-initWithContentsOfFile;-writeToFile:atomically。
当然也可以通过代码直接创建plist文件。
②对象归档是将对象归档以文件的形式保存到磁盘中(也称为序列化,持久化),使用的时候读取该文件的保存路径读取文件的内容(也称为接档,反序列化)。
简单对象归档
使用两个类:NSKeyedArichiver、NSKeyedUnarchiver
例子:使用两个类:NSKeyedArichiver、NSKeyedUnarchiver
NSString *homeDirectory = NSHomeDirectory(); //获取根目录
NSString homePath = [homeDirectory stringByAppendingPathComponent:@"自定义文件名,如test.archiver"];
NSArray *array = @[@"abc", @"123", @12];
Bool flag = [NSKeyedArichiver archiveRootObject:array toFile:homePath];
if(flag) {
NSLog(@"归档成功!");
}
自定义内容归档
归档:
使用NSData实例作为归档的存储数据
添加归档的内容---使用键值对
完成归档
解归档:
从磁盘读取文件,生成NSData实例
根据NSData实例和初始化解归档实例
解归档,根据key访问value
③上述方法都有一个致命的缺点,那就是都无法存储大批量的数据,有性能的问题。
举例:使用归档。
(1)数据的存取都必须是完整的,要求写入的时候要一次性写入,读取的时候要一次性全部读取,这涉及到应用的性能问题。
(2)如果有1000条数据,此时要把第1001条数据存入,那么需要把所有的数据取出来,把这条数据加上去之后,再存入。
创建步骤
1、创建一个简单的View based application
2、选择项目文件,然后选择目标,添加libsqlite3.dylib库到选择框架
3、通过选择" File-> New -> File... -> "选择 Objective C class 创建新文件,单击下一步
4、"sub class of"为NSObject",类命名为DBManager
5、选择创建
6、更新DBManager,
④Core Data是苹果官方推荐使用的数据持久化方式,在使用的过程中,不需要导入数据库框架,也不需要使用sql语句操作数据库,完全是按照面向对象的思想,使用实体模型来操作数据库。在使用的过程中需要注意的是,如果模型发生了变化,可以选择重新生成实体类文件,但是自动生成的数据库并不会自动更新,需要考虑重新生成数据库,并把之前数据库中数据进行移植。Core Data能够简化操作,但是它不支持跨平台使用,如果想实现跨平台,就需要使用SQLite来进行数据持久化。
65、ios中bound 和frame区别
frame指的是:该View在父View坐标系统中的位置和大小。(参照点是父亲的坐标系统)
bounds指的是:该View在本身坐标系统中的位置和大小。(参照点是本身坐标系统)
bounds大小改变 frame 也改变
66、服务器连接三次握手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送连接请求到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到客户端连接请求,向客户端发送允许连接应答,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的允许连接应答,向服务器发送确认,客户端和服务器进入通信状态,完成三次握手。
(所谓的三次握手就是要有三次连接信息的发送/接收过程。TCP连接的建立需要进行三次连接信息的发送/接收。)
67、 GCD有哪三种队列和用法
1. The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
2. Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue(0,0)函数传入优先级来访问队列。
3.用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create(,)1.队列名称 2.队列的类型 并行队列DISPATCH_QUEUE_CONCURRENT 串行队列DISPATCH_QUEUE_SERIAL
68.CALayer 和UiView和绘图的Api的关系
两者最大的区别是,图层不会直接渲染到屏幕上,UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView本身更像是一个CALayer的管理器。一个UIView上可以有n个CALayer,每个layer显示一种东西,增强UIView的展现能力。
69、动画矩阵变换算法
仿射是动画基础,不能熟练使用也肯定玩不好动画特效的 。仿射变换AffineTransform,在iOS中他的实现类是CGAffineTransform和CATransform3D。
仿射变换的矩阵计算
仿射计算中,(以二维坐标为例,坐标点为x,y)我们设我们的坐标点矩阵为
A = [x y 1]
仿射变换基础矩阵为:
//仿射基础矩阵
B = [ ]
a b 0
c d 0
tx ty 1
[ ]
根据矩阵计算规则我们知道A x B的结果是一个1行3列的矩阵,设A x B得到的新矩阵C ,那么C的矩阵应该为
C = [ (a*x+c*y+tx) (b*x+d*y+ty) (1) ]
设C为 = [x‘ y‘ 1] , 那么可以得到
x‘ = a*x + c*y + tx
y‘ = b*x + d*y + ty
这步很关键。根据这个公式,那么仿射矩阵就可以分成5种分别对应
• 平移(Translation)
• 缩放(Scale)
• 翻转(Flip)
• 旋转(Rotation)
• 剪切(Shear)
平移(Translation)
//向右移动300的仿射效果
let translate = CGAffineTransformMakeTranslation(300, 0)
//使用仿射基础方法CGAffineTransformMake ( CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty )
let translate = CGAffineTransformMake(1,0,0,1,300,0)
缩放(Scale)
代码
//x和y都放大1倍
//let scaleAffine = CGAffineTransformMakeScale(2, 2)
//使用仿射基础方法CGAffineTransformMake
let scaleAffine = CGAffineTransformMake(2,0,0,2,0,0)
剪切(Shear)
代码
//使用仿射基础方法CGAffineTransformMake,设置x和y都为0.5的斜切
//斜切效果只能用CGAffineTransformMake实现,但是通过CATransform3DMakeRotation可以有类似的效果
let shearAffine = CGAffineTransformMake(1,0.5,0.5,1,0,0)
旋转(Rotation)
//仿射旋转矩阵
[ ]
cosa sina 0
-sina cosa 0
0 0 1
[ ]
代码
let rotation = CGAffineTransformMake(CGFloat( cos(M_PI_4) ), CGFloat( sin(M_PI_4) ), -CGFloat( sin(M_PI_4) ), CGFloat( cos(M_PI_4) ), 0, 0)
翻转(Flip)
/Flip仿射,要是有3D去实现
let flip = CATransform3DMakeRotation(angle, x, y, z)
//示例
let flipX = CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0)
let flipY = CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0)
let flipZ = CATransform3DMakeRotation(CGFloat(M_PI), 0, 0, 1)
3D仿射变换
3D仿射在iOS中是通过CATransform3D实现的,它有着与CGAffineTrans类似的一组API,但他们有个重要的区别在于 CATransform3D的效果只能加在layer的transform属性上 ,而CGAffineTransform直接加在View上
3D仿射常用的方法
//位移3D仿射
CATransform3DMakeTranslation
CATransform3DTranslation
//旋转3D仿射
CATransform3DMakeRotation
CATransform3DRotation
//缩放3D仿射
CATransform3DMakeScale
CATransform3DScale
//叠加3D仿射效果
CATransform3DConcat
//仿射基础3D方法,可以直接做效果叠加
CGAffineTransformMake (sx,shx,shy,sy,tx,ty)
/*
这个是一个初始化矩阵,带入矩阵算法计算后的结构会得到
x‘=x , y‘=y , z‘=z
它的作用是清除之前对矩阵设置的仿射效果,或者用来初始化一个原始无效果的仿射矩阵
[ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
*/
CATransform3DIdentity
//检查是否有做过仿射3D效果
CATransform3DIsIdentity(transform)
//检查是否是一个仿射3D效果
CATransform3DIsAffine(transform)
//检查2个3D仿射效果是否相同
CATransform3DEqualToTransform(transform1,transform2)
//3D仿射效果反转(反效果,比如原来扩大,就变成缩小)
CATransform3DInvert(transform)
//2D仿射转换3D仿射
CATransform3DGetAffineTransform(transform)
CATransform3DMakeAffineTransform(transform)