实现NSCoding
NSCoding
是一个协议,只有两个方法。
-
encodeWithCoder:
将对象通过NSCoder
转成NSData
。 -
initWithCoder:
通过NSCoder
,再把NSData
转回对象。
@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;
@end
>归档/解档,详细细节(略)
>
>####State Preservation and Restoration
>* iOS6 新增 API,让 APP 可以在开始的时候,可以立即到上次关闭 APP 时的状态,方便用户恢复到之前的动作,而不受 APP 的开关闭/开启而打断。
>* **原理**:在应用程序关闭的时候,将 APP 的状态统统保存起来,下次应用程序开启的时候,如果发现存在之前保存的状态,就读取出来,重建上次保存的控制器。
>
>* 保存控制器的方法
> * `- (void)encodeRestorableStateWithCoder:(NSCoder *)coder`
> * `- (void)decodeRestorableStateWithCoder:(NSCoder *)coder`
>* 在`AppDelegate`则要实现
> * `application: shouldSaveApplicationState:`
> * `application: shouldRestoreApplicationState:`
> * `application: willEncodeRestorableStateWithCoder:`
> * `application: didDecodeRestorableStateWithCoder:`
> * `application: willFinishLaunchingWithOptions:`
> * 步骤:
> * 在程序关闭时,系统通过`application: shouldSaveApplicationState:`询问是否保存,返回 `BOOL` 值。
> * 在返回需要保存时,系统就会通过`application: shouldRestoreApplicationState:`,提供我们一个`NSCoder`,把必要的状态保存起来。如果 App 里面有一个导航控制器,而我们想把整个导航控制器存储起来,可以这样写:
>
> ```swift
> - (void)application:(UIApplication *)application
willEncodeRestorableStateWithCoder:(NSCoder *)coder
{
NSMutableArray *viewControllers = [self.navigationControllers
.viewControllers copy];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:v
iewControllers];
[coder encodeObject:data forKey:@"viewControllers"];
}
> ```
> * 在程序重新启动时,如果系统发现之前已通过`NSCoder`保存状态,就会通过` application: shouldRestoreApplicationState:`,询问是否使用上次的状态,返回布尔值。
> * 接下来,`application: didDecodeRestorableStateWithCoder:`就会被调用到,如果想要复原上次存起来的导航控制器,可以这样写:
>
> ```swift
> - (void)application:(UIApplication *)application
didDecodeRestorableStateWithCoder:(NSCoder *)coder
{
NSData *data = [coder decodeObjectForKey:@"viewControllers"]
;
NSArray *viewControllers = [NSKeyedUnarchiver unarchiveObjec
tWithData:data];
self.navigationController.viewControllers = viewControllers;
}
> ```
##Crash Reports(崩溃报表)
>####通过`Xcode`收集
>* 链接真机,在 Xcode的设置条中,选择 `Window` -> `Devices`。
>
![Snip20170328_4.png](http://upload-images.jianshu.io/upload_images/2390274-eb53513f0cc8aa0f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>
![Snip20170328_7.png](http://upload-images.jianshu.io/upload_images/2390274-b99d09c958f75fca.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>* 在发生`crash`时,在`console`上面同时也会打印出来一些重要的信息。
>
![Snip20170328_8.png](http://upload-images.jianshu.io/upload_images/2390274-68f5886d8189133c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>
>####通过iTunes Connect收集
>* 在 `iTunes Connect` 中 指定 APP 的详细信息内,最下方,有一个额外信息:**崩溃报告**
>* 在 Xcode 的设置条中,选择 `Window` -> `Organizer`,也可以浏览线上的崩溃报告,是浏览变的方便,但都无法找到特定的用户。
>
![Snip20170329_1.png](http://upload-images.jianshu.io/upload_images/2390274-8201f6ae8fb031fe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>
>####直接在设备上浏览(略)
>####通过第三方服务收集(略)
##Core Animation
>####CALayer
>iOS 上从某个`view`上面的`CALayer`开始着手。Mac 上的`NSView`预设没有`CALayer`,需要先把`NSView`的`wantsLayer`设置成`YES`,然后自己建立一个`CALayer`对象,设置`NSView`的`layer`属性。
>
>####CALayer与UIView的关系
>* `UIView`的外观呈现,都是由`Core Animation`实现,看到的`UIView`的样子,其实是里面的`CALayer`的样子。
>* `UIView`里面的`CALayer`本身就具有产生动画的能力,而改动`CALayer`的任何属性,都会产生 0.25 秒的动画,只是`UIKit`的设计是刻意把动画关闭了。
>* `drawRect:`用途不是绘制 `view`,而是绘制`CALayer`的内容。
>* `drawViewHierarchyInRect:afterScreenUpdates:`:iOS7 之后,由于此时的 UI 设计大量使用半透明毛玻璃效果的`View`,而用`CALayer`截出的图片无法抓到这部分。而新的 API 可以抓到无论是`UIKit`、`Quartz`、`OpenGL ES`、`SpriteKit`等这种绘图系统产生的画面。
>
> > ```swift
> > + (UIImage *)screenshotOfView:(UIView *)view{
> > if (CGRectIsEmpty(view.frame)) {
return nil;
}
UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, 0.0);
if ([view respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
// afterScreenUpdates的参数尽量设置为NO
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
}
else{
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
> > ```
>
>
>####设定`CALayer`的基本样式与属性
>* 因为改变任何属性都会产生动画,所以在建立`layer`之后,通常会先设定好`frame`,才把`layer`加到`super layer`上,不然反过来就会产生很奇怪的动画效果。
>* `CALayer`在建立完后,默认是一倍清晰度,所以在`Retina Display`的设备上看起来都会模糊。需要告诉`CALayer`应该要用怎样的清晰度,通过设定`contentsScale`属性
> * `layer.contentsScale = [UIScreen mainScreen].scale;`
>
> ####实现`drawInContext:`注意
> ```swift
> - (void)drawInContext:(CGContextRef)ctx
{
UIGraphicsPushContext(ctx);
// Your drawing code here.
UIGraphicsPopContext();
}
> ```
* 详细部分会从其他书籍笔记中概括
##Audio APIs
>####System Sound Services
>* 播放系统提示音
>* `AudioServicesCreateSystemSoundID` 和 `AudioServicesPlaySystemSound`
>
>```swift
>- (IBAction)testSystemSound:(id)sender
{
SystemSoundID soundID;
NSString *strSoundFile = [[NSBundle mainBundle] pathForResource:@"alertsound" ofType:@"wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:strSoundFile],&soundID);
AudioServicesPlaySystemSound(soundID);
}
>```
>
>####OpenAL
>* 一般是用于游戏中提供立体的音效。
>
>####NSSound、QuickTime、AV Foundation
>* `NSSound`:主要用于在`Mac`上播放简短的提示音效,但提供了很多接口,可以支持多种格式,循环播放,调整音量等。可以说是一个完整的`Audio Player`,不过定位还是偏向用来播放系统提示音效
>
>* `AV Foundation`:按照出现时间排序
> * `AVAudioPlayer`:支持多种格式,但只能播放本地的文件,无法在后台播放
> * `AVPlayer`:iOS4 推出,可以满足绝大部分要求
> * `AVAudioEngine`
>
> ####Audio Queue
> * 更底层的用来播放与制作的 C API
> * 提供更多的播放效果,需要解密后播放。
##总结
* 做一个简单的个人总结,同时推荐给大家本书的大概内容。
* 第一次写笔记,会不断总结经验,不断完善技巧,多多包涵。
>本书较为底层的概括了相关技术点,但个人感觉不是很深入。适合有一定开发经验的人概括性阅读,理解浅显的相关底层工作原理,做一个复习和巩固,但不适合作为研究深入的书籍。相关知识点还是解释的蛮详细的。
>重点介绍了`Audio APIs`,因为`KKBOX`就是一款音乐服务,从事一些跟`Audio`相关的开发。
>本笔记做了相关浓缩和整理。
>但任有少部分内容未做整理,主要原因:一坨一坨代码加文字,真没心情写。