iOS六、七、八、9新特性总汇和适配说明

转自:http://blog.6ag.cn/1195.htmlhtml

iOS6新特性ios

1、关于内存警告web

ios6中废除了viewDidUnload,viewWillUnload这两个系统回调,收到内存警告时在didReceiveMemoryWarning中进行相关的处理。数组

Crayon Syntax Highlighter v2.7.1xcode

- (void)viewDidUnload {浏览器

    [super viewDidUnload];安全

    // 处理 ios6 如下的系统内存警告系统回调消息服务器

}网络

 

// 这里处理ios6 的内存警告app

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    

    float sysVer = [[[UIDevice currentDevice] systemVersion] floatValue];

    //ios6 的特殊处理

    

    if (sysVer >= 6.0f) {

        // 保证 invisible,  由于即便在当前界面也会收到系统回调

        if (self.view.window == nil) {

            //.......

            // 作相关的释放操做

            self.view = nil;   // 确保下次会从新加载

        }

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

- (void)viewDidUnload {

    [super viewDidUnload];

    // 处理 ios6 如下的系统内存警告系统回调消息

}

 

// 这里处理ios6 的内存警告

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    

    float sysVer = [[[UIDevice currentDevice] systemVersion] floatValue];

    //ios6 的特殊处理

    

    if (sysVer >= 6.0f) {

        // 保证 invisible,  由于即便在当前界面也会收到系统回调

        if (self.view.window == nil) {

            //.......

            // 作相关的释放操做

            self.view = nil;   // 确保下次会从新加载

        }

    }

}

[Format Time: 0.0037 seconds]

 

2、关于屏幕旋转

一样ios6 废除了shouldAutorotateToInterfaceOrientation这个旋转屏幕的设置接口。

必须在两个新接口中设置旋转属性:shouldAutorotate、supportedInterfaceOrientations。

收到旋转事件后的处理,一样在willRotateToInterfaceOrientation和didRotateFromInterfaceOrientation中进行。

3、UISwitch

ios6下,新增了如下几个属性,能够设置开关的颜色以及背景图。

Crayon Syntax Highlighter v2.7.1

@property (nonatomic,  retain) UIColor *tintColor;

 

@property (nonatomic,  retain) UIColor *thumbTintColor;

 

@property (nonatomic,  retain) UIImage *onImage;

 

@property (nonatomic,  retain) UIImage *offImage;

1

2

3

4

5

6

7

@property (nonatomic,  retain) UIColor *tintColor;

 

@property (nonatomic,  retain) UIColor *thumbTintColor;

 

@property (nonatomic,  retain) UIImage *onImage;

 

@property (nonatomic,  retain) UIImage *offImage;

[Format Time: 0.0017 seconds]

 

4、UINavigationBar

ios6新增了,设置阴影图片的属性。

Crayon Syntax Highlighter v2.7.1

@property (nonatomic, retain) UIImage *shadowImage;

1

@property (nonatomic, retain) UIImage *shadowImage;

[Format Time: 0.0005 seconds]

 

5、UIImage

能够在ios6下设置图片的scale比例尺寸了。

Crayon Syntax Highlighter v2.7.1

+ (UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;

 

- (id)initWithData:(NSData *)data scale:(CGFloat)scale;

1

2

3

+ (UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;

 

- (id)initWithData:(NSData *)data scale:(CGFloat)scale;

[Format Time: 0.0011 seconds]

 

6、UIRefreshControl

以前苹果官方是没有现成的下拉刷新的控件,都是本身实现或者使用比较成熟的开源库。

ios6苹果加入了UIRefreshControl,配合UITableView直接实现下拉刷新。

7、UICollectionView

全新的集合控件,应用场景有相似照片墙,瀑布流等。

iOS7新特性

1、已禁用-[UIDevice uniqueIdentifier]

苹果老是把用户的隐私看的很重要。-[UIDevice uniqueIdentifier]在iOS5实际在iOS5的时候已经被遗弃了,可是iOS7中已经彻底的禁用了它。Xcode5甚至不会容许你编译包含了指引到-[UIDevice uniqueIdentifier]的app。

此外,iOS7以前的使用了-[UIDevice uniqueIdentifier] 的app若是在iOS7上运行,它不会返回设备的UUID,而是会返回一串字符串,以FFFFFFFF开头,跟着-[UIDevice identifierForVendor]的十六进制值。

2、UIPasteboard由共享变为沙盒化了

UIPasteboard过去是用来作app之间的数据分享的。UIPasteboard本无问题,可是开发者开始使用它来存储标识符,和其余的相关app分享这些标识符的时候问题就出现了。有一个使用这种把戏的就是OpenUDID。

在iOS7中,使用 +[UIPasteboard pasteboardWithName:create:]和 +[UIPasteboard pasteboardWithUniqueName]建立剪贴板,并且只对相同的app group可见,这样就让OpenUDID不那么有用了。

3、MAC地址不能再用来设别设备

还有一个生成iOS设备惟一标示符的方法是使用iOS设备的Media Access Control(MAC)地址。一个MAC地址是一个惟一的号码,它是物理网络层级方面分配给网络适配器的。这个地址苹果还有其余的名字,好比说是硬件地址(Hardware Address)或是Wifi地址,都是指一样的东西。

有不少工程和框架都使用这个方法来生成惟一的设备ID。好比说ODIN。然而,苹果并不但愿有人经过MAC地址来分辨用户,因此若是你在iOS7系统上查询MAC地址,它如今只会返回02:00:00:00:00:00。

如今苹果明确的代表你应该使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来做为你框架和应用的惟一标示符。坦白的来讲,应对这些变化也不是那么的难,见如下代码片断:

Crayon Syntax Highlighter v2.7.1

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];

 

NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];

1

2

3

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];

 

NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];

[Format Time: 0.0010 seconds]

每种方法都适配一种特别的用法:

identifierForVendor对供应商来讲是惟一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,若是用户删除了这个供应商的app而后再从新安装的话,这个标识符就会不一致。

advertisingIdentifier会返回给在这个设备上全部软件供应商相同的 一个值,因此只能在广告的时候使用。这个值会由于不少状况而有所变化,好比说用户初始化设备的时候便会改变。

4、iOS如今要求app如需使用麦克风,须要征得用户赞成

之前若是app须要使用用户的位置,通信录,日历,提醒以及照片,接受推送消息,使用用户的社交网络的时候须要征得用户的赞成。如今在iOS7当中,使用麦克风也须要取得用户赞成了。若是用户不容许app使用麦克风的话,那么须要使用麦克风的app就不能接收不到任何声音。

如下的代码是用来查询用户是否容许app使用麦克风:

Crayon Syntax Highlighter v2.7.1

//第一次调用这个方法的时候,系统会提示用户让他赞成你的app获取麦克风的数据

// 其余时候调用方法的时候,则不会提醒用户

// 而会传递以前的值来要求用户赞成

[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {

    if (granted) {

        // 用户赞成获取数据

    } else {

        // 能够显示一个提示框告诉用户这个app没有获得容许?

    }

}];

1

2

3

4

5

6

7

8

9

10

//第一次调用这个方法的时候,系统会提示用户让他赞成你的app获取麦克风的数据

// 其余时候调用方法的时候,则不会提醒用户

// 而会传递以前的值来要求用户赞成

[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {

    if (granted) {

        // 用户赞成获取数据

    } else {

        // 能够显示一个提示框告诉用户这个app没有获得容许?

    }

}];

[Format Time: 0.0013 seconds]

你同时还要注意,若是你在得到用户的赞成以前使用任何方法来使用麦克风的话,会引发iOS系统弹出如下警示栏:

 

5、[NSArray firstObject]的实现

-[NSArray firstObject]多是Objective-C中被调用作多的API。在Open Radar上一个简单的调查显示有一些需求苹果已经作了记录。好消息是如今这些需求已经获得了解决。. firstObject的使用能够追溯到iOS4.0,可是那时仅仅是一个私有方法。在iOS7之前,工程师用下面的方式来使用它:

Crayon Syntax Highlighter v2.7.1

NSArray *arr = @[];

id item = [arr firstObject];

 

// 在以前你须要作如下工做

id item = [arr count] > 0 ? arr[0] : nil;

1

2

3

4

5

NSArray *arr = @[];

id item = [arr firstObject];

 

// 在以前你须要作如下工做

id item = [arr count] > 0 ? arr[0] : nil;

[Format Time: 0.0012 seconds]

由于上面的方式很日常,有些人将它做为一个类增长到NSArray中,而后建立他们本身的firstObject方法。

这个方法的问题是这个方法的名字必须是惟一的,不然的话这个方法所引起的问题没法预估。

请确保检查你是否有任何自定义的代码在NSArray上实现了firstObject,若是有的话看看它是不是必须的,不是必须的话就把它所有移除。

6、增长了instancetype

instancetype让iOS7API变得更加难懂。苹果改变了大部分 initializer和简易构造函数(convenience constructors),用instancetype代替id做返回类型。可是这个instancetype是什么呢?

instancetype用来在声明一个方法时告诉编译器其返回类型,它表示返回调用该方法的类的对象。

这比以前返回id的一般作法要好,编译器能够对返回类型作一些检查,若是出现错误,在编译时就能提醒你,而不是在程序运行时发生崩溃。

同时,在调用子类方法时,使用它还能够省去对返回值的强制类型转换,编译器可以正确推断方法的返回值类型。

要说到instancetaype的缺点和优势吗?基本上,在任何可能的状况下均可以使用它。

7、设置UIImage的渲染模式:UIImage.renderingMode

着色(Tint Color)是iOS7界面中的一个重大改变,你能够设置一个UIImage在渲染时是否使用当前视图的Tint Color。

UIImage新增了一个只读属性:renderingMode,对应的还有一个新增方法:imageWithRenderingMode:,它使用UIImageRenderingMode枚举值来设置图片的renderingMode属性。该枚举中包含下列值:

Crayon Syntax Highlighter v2.7.1

// 根据图片的使用环境和所处的绘图上下文自动调整渲染模式

UIImageRenderingModeAutomatic 

 

// 始终绘制图片原始状态,不使用Tint Color

UIImageRenderingModeAlwaysOriginal 

 

// 始终根据Tint Color绘制图片,忽略图片的颜色信息

UIImageRenderingModeAlwaysTemplate

1

2

3

4

5

6

7

8

// 根据图片的使用环境和所处的绘图上下文自动调整渲染模式

UIImageRenderingModeAutomatic 

 

// 始终绘制图片原始状态,不使用Tint Color

UIImageRenderingModeAlwaysOriginal 

 

// 始终根据Tint Color绘制图片,忽略图片的颜色信息

UIImageRenderingModeAlwaysTemplate

[Format Time: 0.0005 seconds]

renderingMode属性的默认值是UIImageRenderingModeAutomatic,即UIImage是否使用Tint Color取决于它显示的位置。其余状况能够看下面的图例:

 

如下的代码说明了使用一个既定的rendering模式建立图片是多么简单:

Crayon Syntax Highlighter v2.7.1

UIImage *img = [UIImage imageNamed:@"myimage"];

 

img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

1

2

3

UIImage *img = [UIImage imageNamed:@"myimage"];

 

img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

[Format Time: 0.0008 seconds]

 

8、tintcolor VS barTintColor

iOS7中你可使用一个给定的颜色,甚至是记入颜色主题来给整个app着色,帮助你的app脱颖而出。设置app的tint color很简答,只要使用UIView的新属性tintColor便可。

这个属性是否听上去很熟悉呢?应该很熟悉,有些类,好比说UINaviagtionBar,UISearchBar,UITabBar以及UIToolbar已经有了这么命名的属性。他们如今有了一个新的属性:barTintColor。

为了不使用新属性的时候犯错误,若是你的appp须要支持iOS6之前的系统的时候,请检查一下。

Crayon Syntax Highlighter v2.7.1

UINavigationBar *bar = self.navigationController.navigationBar;

UIColor *color = [UIColor greenColor];

 

if ([bar respondsToSelector:@selector(setBarTintColor:)]) { // iOS 7+

    bar.barTintColor = color;

} else { // what year is this? 2012?

    bar.tintColor = color;

}

1

2

3

4

5

6

7

8

UINavigationBar *bar = self.navigationController.navigationBar;

UIColor *color = [UIColor greenColor];

 

if ([bar respondsToSelector:@selector(setBarTintColor:)]) { // iOS 7+

    bar.barTintColor = color;

} else { // what year is this? 2012?

    bar.tintColor = color;

}

[Format Time: 0.0020 seconds]

 

9、去掉了纹理颜色

 

纹理颜色?对,再也不使用他们了,不能再建立能够展示纹理的颜色。

根据UIInterface.h文件中的注释,-[UIColor groupTableViewBackgroundColor]应该是要在iOS6当中即被删除了,可是它仅仅只是不像以前那样返回纹理颜色了。然而,如下的颜色在iOS7当中被删除了:

Crayon Syntax Highlighter v2.7.1

+ (UIColor *)viewFlipsideBackgroundColor;

 

+ (UIColor *)scrollViewTexturedBackgroundColor;

 

+ (UIColor *)underPageBackgroundColor;

1

2

3

4

5

+ (UIColor *)viewFlipsideBackgroundColor;

 

+ (UIColor *)scrollViewTexturedBackgroundColor;

 

+ (UIColor *)underPageBackgroundColor;

[Format Time: 0.0008 seconds]

 

10、UIButtonTypeRoundRect被UIButtonTypeSystem取代了

 

在iOS开发刚开始就陪伴着你的老朋友如今也被删除了,它就是UIButtonTypeRoundRect ,被新的UIButtonTypeSystem取代了。

若是每次iOS系统的发布都没有一些新的功能会是什么样子?这些新功能相信大部分开发者已经知道了,你可能会发现一些新颖的方式将它们整合到你的app中去!

11、检查无线路由是否可用

定制一个视频播放器的能力在iOS版本每次的发布中一直有所进步。好比说,在iOS6以前,你不能在MPVolumeView中改变AirPlay的icon。

在iOS7当中,你能够经过AirPlay,蓝牙或是其余的虚线机制了解是否有一个远程的设备可用。了解它的话,就可让你的app在恰当的时候作恰当的事,好比说,在没有远程设备的时候就不显示AirPlay的icon。

如下是新增长到MPVolumeView的新属性和推送

Crayon Syntax Highlighter v2.7.1

@property (nonatomic, readonly) BOOL wirelessRoutesAvailable; //  是否有设备能够链接的无线线路?

@property (nonatomic, readonly) BOOL wirelessRouteActive; // 设备如今是否链接上了网络

NSString *const MPVolumeViewWirelessRoutesAvailableDidChangeNotification;

NSString *const MPVolumeViewWirelessRouteActiveDidChangeNotification;

1

2

3

4

@property (nonatomic, readonly) BOOL wirelessRoutesAvailable; //  是否有设备能够链接的无线线路?

@property (nonatomic, readonly) BOOL wirelessRouteActive; // 设备如今是否链接上了网络

NSString *const MPVolumeViewWirelessRoutesAvailableDidChangeNotification;

NSString *const MPVolumeViewWirelessRouteActiveDidChangeNotification;

[Format Time: 0.0014 seconds]

 

12、了解蜂窝网络

在iOS7以前,是使用Reachability来检测设备是否链接到WWAN或是Wifi的。iOS7在这个基础上更进了一步,它会告诉你的设备链接上的是那种蜂窝网络,好比说是Edge网络,HSDPA网络,或是LTE网络。告诉用户他们链接上的是哪一种网络能够优化用户体验,由于这样他们会知道网速如何,不会去请求须要高网速的网络请求。

这是CTTelephonyNetworkInfo的部分功能,它是CoreTelephony框架的一部分。iOS7还增长了currentRadioAccessTechnology属性和CTRadioAccessTechnologyDidChangeNotification到这个类。还有一些新的字符串常量来定义可能的值,好比说是CTRadioAccessTechnologyLTE。

如下代码告诉你在app delegate中如何使用这个新功能:

Crayon Syntax Highlighter v2.7.1

@import CoreTelephony.CTTelephonyNetworkInfo; // new modules syntax!

@interface AppDelegate ()

// we need to keep a reference to the CTTelephonyNetworkInfo object, otherwise the notifications won't be fired!

@property (nonatomic, strong) CTTelephonyNetworkInfo *networkInfo;

@end

 

@implementation ViewController

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // whatever stuff your method does...

    

    self.networkInfo = [[CTTelephonyNetworkInfo alloc] init];

    NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology);

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:

     CTRadioAccessTechnologyDidChangeNotification object:nil];

    

    // whatever stuff your method does...

}

 

- (void)radioAccessChanged {

    NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology);

}

 

@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

@import CoreTelephony.CTTelephonyNetworkInfo; // new modules syntax!

@interface AppDelegate ()

// we need to keep a reference to the CTTelephonyNetworkInfo object, otherwise the notifications won't be fired!

@property (nonatomic, strong) CTTelephonyNetworkInfo *networkInfo;

@end

 

@implementation ViewController

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // whatever stuff your method does...

    

    self.networkInfo = [[CTTelephonyNetworkInfo alloc] init];

    NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology);

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:

     CTRadioAccessTechnologyDidChangeNotification object:nil];

    

    // whatever stuff your method does...

}

 

- (void)radioAccessChanged {

    NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology);

}

 

@end

[Format Time: 0.0054 seconds]

注意:研究一下CTTelephonyNetworkInfo.h 文件来看看是否有其余无线网络类型的的字符串常量。若是设备没有连上的话,currentRadioAccessTechnology 则会返回nil。

十3、经过iCloud同步用户设备的密码

iOS7以及Mavericks增长了iCloud Keychain来提供密码,以及iCloud中一些敏感数据的同步。开发者能够经过keychain中的kSecAttrSynchronizable key来遍历dictionary对象。

因为直接处理keychain比较难,封装库提供了一个简单的处理keychain的方法。SSKeychain封装库多是最有名的的一个,做为一种福利,如今它支持在iCloud同步。

如下代码片断显示了如何使用SSKeychain:

Crayon Syntax Highlighter v2.7.1

#import <SSKeychain.h>

 

- (BOOL)saveCredentials:(NSError **)error {

    SSKeychainQuery *query = [[SSKeychainQuery alloc] init];

    query.password = @"MySecretPassword";

    query.service = @"MyAwesomeService";

    query.account = @"John Doe";

    query.synchronizable = YES;

    return [query save:&error];

}

 

- (NSString *)savedPassword:(NSError **)error {

    SSKeychainQuery *query = [[SSKeychainQuery alloc] init];

    query.service = @"MyAwesomeService";

    query.account = @"John Doe";

    query.synchronizable = YES;

    query.password = nil;

    if ([query fetch:&error]) {

        return query.password;

    }

    return nil;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#import <SSKeychain.h>

 

- (BOOL)saveCredentials:(NSError **)error {

    SSKeychainQuery *query = [[SSKeychainQuery alloc] init];

    query.password = @"MySecretPassword";

    query.service = @"MyAwesomeService";

    query.account = @"John Doe";

    query.synchronizable = YES;

    return [query save:&error];

}

 

- (NSString *)savedPassword:(NSError **)error {

    SSKeychainQuery *query = [[SSKeychainQuery alloc] init];

    query.service = @"MyAwesomeService";

    query.account = @"John Doe";

    query.synchronizable = YES;

    query.password = nil;

    if ([query fetch:&error]) {

        return query.password;

    }

    return nil;

}

[Format Time: 0.0060 seconds]

不要忘记CocoaPods是快速便捷安装SSKeychian的好方法。

十4、使用NSAttributedString显示HTML

在app中使用webview有时会让人很是沮丧,即便只是显示少许的HTMLneirong ,webview也会消耗大量的内存。如今iOS7让这些变得简单了,你能够从用少许代码在HTML文件中建立一个NSAttributedString,好比:

Crayon Syntax Highlighter v2.7.1

NSString *html = @"<bold>Wow!</bold> Now <em>iOS</em> can create <h3>NSAttributedString</h3> from HTMLs!";

NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};

 

NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:nil];

1

2

3

4

NSString *html = @"<bold>Wow!</bold> Now <em>iOS</em> can create <h3>NSAttributedString</h3> from HTMLs!";

NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};

 

NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:nil];

[Format Time: 0.0017 seconds]

如今你能够在任意的UIKit对象上使用NSAttributedString 了,好比说是一个UILabel或是一个UITextField。

注意:NSHTMLTextDocumentType 只是NSDocumentTypeDocumentAttribute key一种可能的值。你还可使用NSPlainTextDocumentType,NSRTFTextDocumentType或是NSRTFDTextDocumentType。

你还能够从NSAttributedString中建立一个HTML字符串,以下:

Crayon Syntax Highlighter v2.7.1

NSAttributedString *attrString; // from previous code

NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};

 

NSData *htmlData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:options error:nil];

NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];

1

2

3

4

5

NSAttributedString *attrString; // from previous code

NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};

 

NSData *htmlData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:options error:nil];

NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];

[Format Time: 0.0021 seconds]

如今你估计在app中会更多的使用HTML了。

十5、使用原生的Base64

Base64是使用ASCII码显示二进制数据的一种流行方法。直到如今,开发者还不得不使用开源的工具来编码解码Base64的内容。

如今iOS7引入了如下四种新的NSData方法来操做Base64编码的数据:

Crayon Syntax Highlighter v2.7.1

// From NSData.h

- (id)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options;

 

- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options;

 

- (id)initWithBase64EncodedData:(NSData *)base64Data options:(NSDataBase64DecodingOptions)options;

 

- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options;

1

2

3

4

5

6

7

8

// From NSData.h

- (id)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options;

 

- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options;

 

- (id)initWithBase64EncodedData:(NSData *)base64Data options:(NSDataBase64DecodingOptions)options;

 

- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options;

[Format Time: 0.0021 seconds]

这些方法能够帮助你轻易的将NSData对象转化为Base64,或者将Base64转化为NSData object。见如下的例子:

Crayon Syntax Highlighter v2.7.1

NSData* sampleData = [@"Some sample data" dataUsingEncoding:NSUTF8StringEncoding];

 

NSString * base64String = [sampleData base64EncodedStringWithOptions:0];

NSLog(@"Base64-encoded string is %@", base64String); // prints "U29tZSBzYW1wbGUgZGF0YQ=="

 

NSData* dataFromString = [[NSData alloc] initWithBase64EncodedString:base64String options:0];

NSLog(@"String is %@",[NSString stringWithUTF8String:[dataFromString bytes]]); // prints "String is Some sample data"

1

2

3

4

5

6

7

NSData* sampleData = [@"Some sample data" dataUsingEncoding:NSUTF8StringEncoding];

 

NSString * base64String = [sampleData base64EncodedStringWithOptions:0];

NSLog(@"Base64-encoded string is %@", base64String); // prints "U29tZSBzYW1wbGUgZGF0YQ=="

 

NSData* dataFromString = [[NSData alloc] initWithBase64EncodedString:base64String options:0];

NSLog(@"String is %@",[NSString stringWithUTF8String:[dataFromString bytes]]); // prints "String is Some sample data"

[Format Time: 0.0025 seconds]

若是你须要支持iOS6或者更早之前的系统,你可使用如下两个方法:

Crayon Syntax Highlighter v2.7.1

/* These methods first appeared in NSData.h on OS X 10.9 and iOS 7.0. They are deprecated in the same releases in favor of

 the methods in the <code>NSDataBase64Encoding</code> category. However, these methods have existed for several releases, so

 they may be used for applications targeting releases prior to OS X 10.9 and iOS 7.0.

 */

- (id)initWithBase64Encoding:(NSString *)base64String;

- (NSString *)base64Encoding;

1

2

3

4

5

6

/* These methods first appeared in NSData.h on OS X 10.9 and iOS 7.0. They are deprecated in the same releases in favor of

 the methods in the <code>NSDataBase64Encoding</code> category. However, these methods have existed for several releases, so

 they may be used for applications targeting releases prior to OS X 10.9 and iOS 7.0.

 */

- (id)initWithBase64Encoding:(NSString *)base64String;

- (NSString *)base64Encoding;

[Format Time: 0.0008 seconds]

 

十6、使用UIApplicationUserDidTakeScreenshotNotification来检查截图

在iOS7以前,像Snapshot或是Facebook Poke这样的app是使用一些很精巧的方法来检测用户是否有截图。然而,iOS7提供一个崭新的推送方法:UIApplicationUserDidTakeScreenshotNotification。只要像往常同样订阅便可知道何时截图了。

注意:UIApplicationUserDidTakeScreenshotNotification 将会在截图完成以后显示。如今在截图截取以前没法获得通知。但愿苹果会在iOS8当中增长UIApplicationUserWillTakeScreenshotNotification。

十7、实现多语言语音合成

若是可让app说话会不会很好呢?iOS7加入了两个新类:AVSpeechSynthesizer 以及AVSpeechUtterance。这两个类能够给你的app发声。颇有意思不是吗?有多种语言可供选择——Siri不会说的语言也有,好比说巴西葡萄牙语。

使用这两个类给app提供语言合成的功能很是简单。AVSpeechUtterance 表明你想说什么,如何说。AVSpeechSynthesizer 用来发出这些声音,见如下代码片断:

Crayon Syntax Highlighter v2.7.1

AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init];

AVSpeechUtterance *utterance =

[AVSpeechUtterance speechUtteranceWithString:@"Wow, I have such a nice voice!"];

utterance.rate = AVSpeechUtteranceMaximumSpeechRate / 4.0f;

utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]; // defaults to your system language

[synthesizer speakUtterance:utterance];

1

2

3

4

5

6

AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init];

AVSpeechUtterance *utterance =

[AVSpeechUtterance speechUtteranceWithString:@"Wow, I have such a nice voice!"];

utterance.rate = AVSpeechUtteranceMaximumSpeechRate / 4.0f;

utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]; // defaults to your system language

[synthesizer speakUtterance:utterance];

[Format Time: 0.0020 seconds]

 

十8、使用了新的UIScreenEdgePanGestureRecognizer

UIScreenEdgePanGestureRecognizer 继承自UIPanGestureRecognizer ,它可让你从屏幕边界便可检测手势。

使用新的手势识别器很简单,见如下:

Crayon Syntax Highlighter v2.7.1

UIScreenEdgePanGestureRecognizer *recognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleScreenEdgeRecognizer:)];

recognizer.edges = UIRectEdgeLeft;

[self.view addGestureRecognizer:recognizer];

1

2

3

UIScreenEdgePanGestureRecognizer *recognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleScreenEdgeRecognizer:)];

recognizer.edges = UIRectEdgeLeft;

[self.view addGestureRecognizer:recognizer];

[Format Time: 0.0013 seconds]

 

十9、使用UIScrollViewKeyboardDismissMode实现了Message app的行为

像Messages app同样在滚动的时候可让键盘消失是一种很是好的体验。然而,将这种行为整合到你的app很难。幸运的是,苹果给UIScrollView添加了一个很好用的属性keyboardDismissMode,这样能够方便不少。

如今仅仅只须要在Storyboard中改变一个简单的属性,或者增长一行代码,你的app能够和办到和Messages app同样的事情了。

这个属性使用了新的UIScrollViewKeyboardDismissMode enum枚举类型。这个enum枚举类型可能的值以下:

Crayon Syntax Highlighter v2.7.1

UIScrollViewKeyboardDismissModeNone        // the keyboard is not dismissed automatically when scrolling

UIScrollViewKeyboardDismissModeOnDrag      // dismisses the keyboard when a drag begins

UIScrollViewKeyboardDismissModeInteractive // the keyboard follows the dragging touch off screen, and may be

pulled upward again to cancel the dismiss

1

2

3

4

UIScrollViewKeyboardDismissModeNone        // the keyboard is not dismissed automatically when scrolling

UIScrollViewKeyboardDismissModeOnDrag      // dismisses the keyboard when a drag begins

UIScrollViewKeyboardDismissModeInteractive // the keyboard follows the dragging touch off screen, and may be

pulled upward again to cancel the dismiss

[Format Time: 0.0007 seconds]

如下是让键盘能够在滚动的时候消失须要设置的属性:

 

二10、使用Core Image来检测眨眼以及微笑

iOS给Core Image增长了两种人脸检测功能:CIDetectorEyeBlink以及CIDetectorSmile。这也就是说你如今能够在照片中检测微笑以及眨眼。

如下是在app中使用它的方法:

Crayon Syntax Highlighter v2.7.1

UIImage *image = [UIImage imageNamed:@"myImage"];

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace

                                          context:nil

                                          options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];

 

NSDictionary *options = @{ CIDetectorSmile: @YES, CIDetectorEyeBlink: @YES };

 

NSArray *features = [detector featuresInImage:image.CIImage options:options];

 

for (CIFaceFeature *feature in features) {

    NSLog(@"Bounds: %@", NSStringFromCGRect(feature.bounds));

    

    if (feature.hasSmile) {

        NSLog(@"Nice smile!");

    } else {

        NSLog(@"Why so serious?");

    }

    if (feature.leftEyeClosed || feature.rightEyeClosed) {

        NSLog(@"Open your eyes!");

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

UIImage *image = [UIImage imageNamed:@"myImage"];

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace

                                          context:nil

                                          options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];

 

NSDictionary *options = @{ CIDetectorSmile: @YES, CIDetectorEyeBlink: @YES };

 

NSArray *features = [detector featuresInImage:image.CIImage options:options];

 

for (CIFaceFeature *feature in features) {

    NSLog(@"Bounds: %@", NSStringFromCGRect(feature.bounds));

    

    if (feature.hasSmile) {

        NSLog(@"Nice smile!");

    } else {

        NSLog(@"Why so serious?");

    }

    if (feature.leftEyeClosed || feature.rightEyeClosed) {

        NSLog(@"Open your eyes!");

    }

}

[Format Time: 0.0055 seconds]

 

二11、给UITextView增长了连接

如今在iOS添加你本身的Twitter帐户更加简单了,如今你能够给一个NSAttributedString增长连接了,而后当它被点击的时候唤起一个定制的action。

首先,建立一个NSAttributedString而后增长给它增长一个NSLinkAttributeName 属性,见如下:

Crayon Syntax Highlighter v2.7.1

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"This is an example by @marcelofabri_"];

[attributedString addAttribute:NSLinkAttributeName

                         value:@"username://marcelofabri_"

                         range:[[attributedString string] rangeOfString:@"@marcelofabri_"]];

 

 

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor],

                                 NSUnderlineColorAttributeName: [UIColor lightGrayColor],

                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

 

// assume that textView is a UITextView previously created (either by code or Interface Builder)

textView.linkTextAttributes = linkAttributes; // customizes the appearance of links

textView.attributedText = attributedString;

textView.delegate = self;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"This is an example by @marcelofabri_"];

[attributedString addAttribute:NSLinkAttributeName

                         value:@"username://marcelofabri_"

                         range:[[attributedString string] rangeOfString:@"@marcelofabri_"]];

 

 

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor],

                                 NSUnderlineColorAttributeName: [UIColor lightGrayColor],

                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

 

// assume that textView is a UITextView previously created (either by code or Interface Builder)

textView.linkTextAttributes = linkAttributes; // customizes the appearance of links

textView.attributedText = attributedString;

textView.delegate = self;

[Format Time: 0.0039 seconds]

这样就可让连接在文本中显示。然而,你也能够控制当连接被点击的时候会发生什么,实现这个可使用UITextViewDelegate协议的新的shouldInteractWithURL方法,就像这样:

Crayon Syntax Highlighter v2.7.1

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {

    if ([[URL scheme] isEqualToString:@"username"]) {

        NSString *username = [URL host];

        // do something with this username

        // ...

        return NO;

    }

    return YES; // let the system open this URL

}

1

2

3

4

5

6

7

8

9

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {

    if ([[URL scheme] isEqualToString:@"username"]) {

        NSString *username = [URL host];

        // do something with this username

        // ...

        return NO;

    }

    return YES; // let the system open this URL

}

[Format Time: 0.0023 seconds]

 

iOS8新特性

1、UIAlertController对alert&actionSheet的封装

UIAlertController.h

提示框按钮的选择

Crayon Syntax Highlighter v2.7.1

typedef NS_ENUM(NSInteger, UIAlertActionStyle) {

    

    UIAlertActionStyleDefault = 0,

    

    UIAlertActionStyleCancel,

    

    UIAlertActionStyleDestructive

    

} NS_ENUM_AVAILABLE_IOS(8_0);

1

2

3

4

5

6

7

8

9

typedef NS_ENUM(NSInteger, UIAlertActionStyle) {

    

    UIAlertActionStyleDefault = 0,

    

    UIAlertActionStyleCancel,

    

    UIAlertActionStyleDestructive

    

} NS_ENUM_AVAILABLE_IOS(8_0);

[Format Time: 0.0010 seconds]

提示框的样式

Crayon Syntax Highlighter v2.7.1

typedef NS_ENUM(NSInteger, UIAlertControllerStyle) {

    

    UIAlertControllerStyleActionSheet = 0,

    

    UIAlertControllerStyleAlert

    

} NS_ENUM_AVAILABLE_IOS(8_0);

 

NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertAction : NSObject <NSCopying>

1

2

3

4

5

6

7

8

9

typedef NS_ENUM(NSInteger, UIAlertControllerStyle) {

    

    UIAlertControllerStyleActionSheet = 0,

    

    UIAlertControllerStyleAlert

    

} NS_ENUM_AVAILABLE_IOS(8_0);

 

NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertAction : NSObject <NSCopying>

[Format Time: 0.0014 seconds]

建立提示框按钮

Crayon Syntax Highlighter v2.7.1

+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *action))handler;

 

@property (nonatomic, readonly) NSString *title;

 

@property (nonatomic, readonly) UIAlertActionStyle style;

 

@property (nonatomic, getter=isEnabled) BOOL enabled;

 

@end

 

NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertController : UIViewController

1

2

3

4

5

6

7

8

9

10

11

+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *action))handler;

 

@property (nonatomic, readonly) NSString *title;

 

@property (nonatomic, readonly) UIAlertActionStyle style;

 

@property (nonatomic, getter=isEnabled) BOOL enabled;

 

@end

 

NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertController : UIViewController

[Format Time: 0.0029 seconds]

建立提示框

Crayon Syntax Highlighter v2.7.1

+ (instancetype)alertControllerWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle;

1

+ (instancetype)alertControllerWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(UIAlertControllerStyle)preferredStyle;

[Format Time: 0.0010 seconds]

添加按钮

Crayon Syntax Highlighter v2.7.1

- (void)addAction:(UIAlertAction *)action;

 

@property (nonatomic, readonly) NSArray *actions;

1

2

3

- (void)addAction:(UIAlertAction *)action;

 

@property (nonatomic, readonly) NSArray *actions;

[Format Time: 0.0008 seconds]

添加文本输入框

Crayon Syntax Highlighter v2.7.1

- (void)addTextFieldWithConfigurationHandler:(void (^)(UITextField *textField))configurationHandler;

 

@property (nonatomic, readonly) NSArray *textFields;

 

@property (nonatomic, copy) NSString *title;

 

@property (nonatomic, copy) NSString *message;

 

@property (nonatomic, readonly) UIAlertControllerStyle preferredStyle;

1

2

3

4

5

6

7

8

9

- (void)addTextFieldWithConfigurationHandler:(void (^)(UITextField *textField))configurationHandler;

 

@property (nonatomic, readonly) NSArray *textFields;

 

@property (nonatomic, copy) NSString *title;

 

@property (nonatomic, copy) NSString *message;

 

@property (nonatomic, readonly) UIAlertControllerStyle preferredStyle;

[Format Time: 0.0023 seconds]

简单实用示例:

Crayon Syntax Highlighter v2.7.1

// 1.建立提示框对象,默认是actionSheet效果

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"注意" message:@"个人呈现方式变了" preferredStyle:UIAlertControllerStyleAlert];

 

// 2.建立取消按钮并添加到提示框上

[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

    

    NSLog(@"取消按钮被点击了");

}]];

 

// 3.呈现提示框

[self presentViewController:alert animated:YES completion:nil];

1

2

3

4

5

6

7

8

9

10

11

// 1.建立提示框对象,默认是actionSheet效果

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"注意" message:@"个人呈现方式变了" preferredStyle:UIAlertControllerStyleAlert];

 

// 2.建立取消按钮并添加到提示框上

[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

    

    NSLog(@"取消按钮被点击了");

}]];

 

// 3.呈现提示框

[self presentViewController:alert animated:YES completion:nil];

[Format Time: 0.0024 seconds]

 

2、UIPopoverController直接经过present方式呈现

UIViewController.h

Crayon Syntax Highlighter v2.7.1

typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {

    

    UIModalPresentationFullScreen = 0,

    

    UIModalPresentationPageSheet NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationFormSheet NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationCurrentContext NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationCustom NS_ENUM_AVAILABLE_IOS(7_0),

    

    UIModalPresentationOverFullScreen NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationOverCurrentContext NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationPopover NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationNone NS_ENUM_AVAILABLE_IOS(7_0) = -1,

    

};

 

@property (nonatomic,readonly) UIPopoverPresentationController *popoverPresentationController NS_AVAILABLE_IOS(8_0);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {

    

    UIModalPresentationFullScreen = 0,

    

    UIModalPresentationPageSheet NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationFormSheet NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationCurrentContext NS_ENUM_AVAILABLE_IOS(3_2),

    

    UIModalPresentationCustom NS_ENUM_AVAILABLE_IOS(7_0),

    

    UIModalPresentationOverFullScreen NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationOverCurrentContext NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationPopover NS_ENUM_AVAILABLE_IOS(8_0),

    

    UIModalPresentationNone NS_ENUM_AVAILABLE_IOS(7_0) = -1,

    

};

 

@property (nonatomic,readonly) UIPopoverPresentationController *popoverPresentationController NS_AVAILABLE_IOS(8_0);

[Format Time: 0.0041 seconds]

使用示例:

Crayon Syntax Highlighter v2.7.1

// 1.建立内容控制器

UITableViewController *contentVc = [[UITableViewController alloc] init];

 

// 2.1 设置呈现方式

contentVc.modalPresentationStyle = UIModalPresentationPopover;

 

// 2.2设置在导航栏的左边按钮呈现

contentVc.popoverPresentationController.barButtonItem = self.navigationItem.leftBarButtonItem;

 

// 3.呈现

[self presentViewController:contentVc animated:YES completion:nil];

1

2

3

4

5

6

7

8

9

10

11

// 1.建立内容控制器

UITableViewController *contentVc = [[UITableViewController alloc] init];

 

// 2.1 设置呈现方式

contentVc.modalPresentationStyle = UIModalPresentationPopover;

 

// 2.2设置在导航栏的左边按钮呈现

contentVc.popoverPresentationController.barButtonItem = self.navigationItem.leftBarButtonItem;

 

// 3.呈现

[self presentViewController:contentVc animated:YES completion:nil];

[Format Time: 0.0019 seconds]

之前的方式:

Crayon Syntax Highlighter v2.7.1

// 1.建立内容控制器

UITableViewController *contentVc = [[UITableViewController alloc] init];

 

// 2.建立popover

UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:contentVc];

 

popover.popoverContentSize = CGSizeMake(100, 100);

 

// 3.呈现

[popover presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

1

2

3

4

5

6

7

8

9

10

// 1.建立内容控制器

UITableViewController *contentVc = [[UITableViewController alloc] init];

 

// 2.建立popover

UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:contentVc];

 

popover.popoverContentSize = CGSizeMake(100, 100);

 

// 3.呈现

[popover presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

[Format Time: 0.0022 seconds]

 

3、获取用户受权的用户隐私保护

地图定位示例 :

Crayon Syntax Highlighter v2.7.1

// 导入定位框架

#import <CoreLocation/CoreLocation.h>

 

@interface ViewController ()<CLLocationManagerDelegate>

 

// 设置定位对象

@property(nonatomic,strong)CLLocationManager* maneger;

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    // 当使用iOS8定位的时候须要请求用户受权,且在info.plist里添加字段NSLocationAlwaysUsageDescription 请求用户受权的描述

    // iOS7仅仅须要在info.plist里添加字段Privacy - Location Usage Description 请求用户受权的描述

    // 不须要再写下面的代码

    if (IOS8) {

        [self.maneger requestAlwaysAuthorization];//请求用户受权 

    }

    

    // 开启定位

    [self.maneger startUpdatingLocation];

    

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

// 导入定位框架

#import <CoreLocation/CoreLocation.h>

 

@interface ViewController ()<CLLocationManagerDelegate>

 

// 设置定位对象

@property(nonatomic,strong)CLLocationManager* maneger;

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    

    // 当使用iOS8定位的时候须要请求用户受权,且在info.plist里添加字段NSLocationAlwaysUsageDescription 请求用户受权的描述

    // iOS7仅仅须要在info.plist里添加字段Privacy - Location Usage Description 请求用户受权的描述

    // 不须要再写下面的代码

    if (IOS8) {

        [self.maneger requestAlwaysAuthorization];//请求用户受权 

    }

    

    // 开启定位

    [self.maneger startUpdatingLocation];

    

}

[Format Time: 0.0037 seconds]

 

4、针对屏幕适配应运而生的size classes

size classes是为了解决storyboard只能订制一种屏幕样式的问题,它再也不是具体的尺寸,而是抽象尺寸经过宽/高 的compact、any、regular 组成了九种组合包含了全部苹果设备的尺寸。

iOS9新特性

1、网络适配

iOS9系统发送的网络请求将统一使用TLS 1.2 SSL。采用TLS 1.2 协议,目的是强制加强数据访问安全,并且系统Foundation框架下的相关网络请求,将再也不默认使用HTTP等不安全的网络协议,而默认采用TLS 1.2。服务器所以须要更新,以解析相关数据。如不更新,可经过在 info.plist 中声明,倒退回不安全的网络请求。

什么是SSL/TLS?跟HTTP和HTTPS有什么关系?

跟往常同样,先说结论:

Crayon Syntax Highlighter v2.7.1

HTTP + SSL/TLS + TCP = HTTPS

1

HTTP + SSL/TLS + TCP = HTTPS

[Format Time: 0.0005 seconds]

TLS 是 SSL 新的别称。举个例子:

“TLS1.0”之于“SSL3.1”,犹“公元2015”之于“民国104”,或者是“一千克”之于“一公斤”,或者是“半斤”之于“八两”:称呼不一样,但意思相同。

SSL 3.0版本以后的迭代版本被从新命名为TLS 1.0,也就是说:

Crayon Syntax Highlighter v2.7.1

TLS 1.0 = SSL 3.1

1

TLS 1.0 SSL 3.1

[Format Time: 0.0004 seconds]

因此他们是一个东西,咱们日常也常常简单见到 “SSL/TLS” 这种说法。经常使用的是下面这些:

Crayon Syntax Highlighter v2.7.1

SSL 2.0

 

SSL 3.0

 

TLS 1.0 (SSL 3.1)

 

TLS 1.1 (SSL 3.1)

 

TLS 1.2 (SSL 3.1)

1

2

3

4

5

6

7

8

9

SSL 2.0

 

SSL 3.0

 

TLS 1.0 (SSL 3.1)

 

TLS 1.1 (SSL 3.1)

 

TLS 1.2 (SSL 3.1)

[Format Time: 0.0010 seconds]

那为何标题是“使用HTTPS”而没有说起SSL和TLS什么事? 要理解这个,要看下一个公式:

Crayon Syntax Highlighter v2.7.1

HTTP + SSL/TLS + TCP = HTTPS

1

HTTP + SSL/TLS + TCP = HTTPS

[Format Time: 0.0005 seconds]

打个比方:若是原来的 HTTP 是塑料水管,容易被戳破;那么现在新设计的 HTTPS 就像是在原有的塑料水管以外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了以后,不容易被戳破。

目前,应用最普遍的是TLS 1.0,接下来是SSL 3.0。可是,主流浏览器都已经实现了TLS 1.2的支持。Apple让你的HTTP采用SSL/TLS协议,就是让你从HTTP转到HTTPS。

之前的HTTP不是也能用吗?为何要用SSL/TLS,闲得慌?!Apple是否是又在反人类?

不使用SSL/TLS的HTTP通讯,就是不加密的通讯!

全部信息明文传播,带来了三大风险:

窃听风险(eavesdropping):第三方能够获知通讯内容。

篡改风险(tampering):第三方能够修改通讯内容。

冒充风险(pretending):第三方能够冒充他人身份参与通讯。

SSL/TLS协议是为了解决这三大风险而设计的,但愿达到:

全部信息都是加密传播,第三方没法窃听。

具备校验机制,一旦被篡改,通讯双方会马上发现。

配备身份证书,防止身份被冒充。

如何适配?---弱弱地问下:加班要多久?

正如文章开头所说:

TLS 1.2 协议 强制加强数据访问安全 系统 Foundation 框架下的相关网络请求,将再也不默认使用 HTTP 等不安全的网络协议,而默认采用 TLS 1.2。服务器所以须要更新,以解析相关数据。如不更新,可经过在 Info.plist 中声明,倒退回不安全的网络请求。

方案一:当即让公司的服务端升级使用TLS 1.2。

方案二:虽Apple不建议,但可经过在 Info.plist 中声明,倒退回不安全的网络请求依然能让App访问指定http,甚至任意的http。

info.plist 配置中的XML源码以下所示:

 

上面是比较严谨的作法,指定了能访问哪些特定的HTTP。固然也有暴力的作法: 完全倒退回不安全的HTTP网络请求,能任意进行HTTP请求,好比你在开发一款浏览器App,或者你想偷懒,或者后台想偷懒,或者公司不给你升级服务器。但目前Apple的官方文档并未说起如何在 info.plist 配置能够参考本文:http://blog.6ag.cn/1065.html

2、更灵活的后台定位

若是不适配iOS9,就不能偷偷在后台定位。不过苹果将容许出现这种场景:

同一App中的多个location manager,一些只能在前台定位,另外一些可在后台定位,并可随时开启或者关闭特定location manager的后台定位。

如何偷偷在后台定位:

Crayon Syntax Highlighter v2.7.1

// 1. 实例化定位管理器

_locationManager = [[CLLocationManager alloc] init];

 

// 2. 设置代理

_locationManager.delegate = self;

 

// 3. 定位精度

[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

 

// 4.请求用户权限:分为:?只在前台开启定位?在后台也可定位,

//注意:建议只请求?和?中的一个,若是两个权限都须要,只请求?便可,

//??这样的顺序,将致使bug:第一次启动程序后,系统将只请求?的权限,?的权限系统不会请求,只会在下一次启动应用时请求?

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {

    //[_locationManager requestWhenInUseAuthorization];//?只在前台开启定位

    [_locationManager requestAlwaysAuthorization];//?在后台也可定位

}

 

// 5.iOS9新特性:将容许出现这种场景:同一app中多个location manager:一些只能在前台定位,另外一些可在后台定位(并可随时禁止其后台定位)。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {

    _locationManager.allowsBackgroundLocationUpdates = YES;

}

 

// 6. 更新用户位置

[_locationManager startUpdatingLocation];

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// 1. 实例化定位管理器

_locationManager = [[CLLocationManager alloc] init];

 

// 2. 设置代理

_locationManager.delegate = self;

 

// 3. 定位精度

[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

 

// 4.请求用户权限:分为:?只在前台开启定位?在后台也可定位,

//注意:建议只请求?和?中的一个,若是两个权限都须要,只请求?便可,

//??这样的顺序,将致使bug:第一次启动程序后,系统将只请求?的权限,?的权限系统不会请求,只会在下一次启动应用时请求?

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {

    //[_locationManager requestWhenInUseAuthorization];//?只在前台开启定位

    [_locationManager requestAlwaysAuthorization];//?在后台也可定位

}

 

// 5.iOS9新特性:将容许出现这种场景:同一app中多个location manager:一些只能在前台定位,另外一些可在后台定位(并可随时禁止其后台定位)。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {

    _locationManager.allowsBackgroundLocationUpdates = YES;

}

 

// 6. 更新用户位置

[_locationManager startUpdatingLocation];

[Format Time: 0.0044 seconds]

可是若是照着这种方式尝试,而没有配置info.plist,100%你的程序会崩溃掉,并报错:

*** Assertion failure in -[CLLocationManager setAllowsBackgroundLocationUpdates:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-1808.1.5/Framework/CoreLocation/CLLocationManager.m:593

要将 info.plist 配置以下:

 

对应的 Info.plist 的XML源码是:

 

3、Bitcode

bitcode的理解应该是把程序编译成的一种过渡代码,而后苹果再把这个过渡代码编译成可执行的程序。bitcode也容许苹果在后期从新优化咱们程序的二进制文件,有相似于App瘦身的思想。将来Watch应用须包含Bitcode,iOS不强制,但Xcode7默认会开启Bitcode。

用了xcode7的编译器编译以前没问题的项目可能会出现下列报错。

XXXX’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode forthistarget. forarchitecture arm64

问题的缘由是:某些第三方库还不支持bitcode。要否则是等待库的开发者升级了此项功能咱们更新库,要不就是把这个bitcode禁用。禁用Bitcode,方法见下图:

 

4、企业级分发

iOS9以前,企业级分发十分方便:点击App出现“信任按钮”。

iOS9之后,企业级分发ipa包将遭到与Mac上dmg安装包同样的待遇。默认不能安装,也再也不出现“信任按钮”,必须让用户进行gif图中的设置。

 

5、URL scheme

URL scheme通常使用的场景是应用程序有分享或跳其余平台受权的功能,分享或受权后再跳回来。在iOS8并无作过多限制,在iOS9中,若是使用URL scheme必须在"info.plist"中将你要在外部调用的URL scheme列为白名单,不然不能使用。

canOpenURL: failed forURL : "mqzone://qqapp"- error: "This app is not allowed to query for scheme mqzone"

具体的解决方案也是要在info.plist中设置 LSApplicationQueriesSchemes 类型为数组,下面添加全部你用到的scheme

 

推荐一篇博客: http://awkwardhare.com/post/121196006730/quick-take-on-ios-9-url-scheme-changes

其中最关键的是如下部分:

If you call the “canOpenURL” method on a URL that is not in your whitelist, it will return “NO”, even if there is an app installed that has registered to handle this scheme. A “This app is not allowed to query for scheme xxx” syslog entry will appear.

If you call the “openURL” method on a URL that is not in your whitelist, it will fail silently. A “This app is not allowed to query for scheme xxx” syslog entry will appear.

6、新字体

iOS8中,字体是Helvetica,中文的字体有点相似于“华文细黑”。只是苹果手机自带渲染,因此看上去可能比普通的华文细黑要美观。iOS9中,中文系统字体变为了专为中国设计的“苹方” 有点相似于一种word字体“幼圆”。字体有轻微的加粗效果,而且最关键的是字体间隙变大了!

因此不少本来写死了width的label可能会出现“...”的状况。

 

 

上面这两张图也能够直观的看出同一个界面,同一个label的变化。

因此为了在界面显示上不出错,就算是固定长度的文字也仍是建议使用sizetofit 或者ios向上取整 ceilf() 或者提早计算。

Crayon Syntax Highlighter v2.7.1

CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];

CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

1

2

CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];

CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

[Format Time: 0.0013 seconds]

 

7、tableview

虽然如今的iOS9已经推送正式版了,可是iOS9使用时仍是会感受到App比之前更加卡顿了,tableView拖动时卡顿显示的最为明显。 而且以前遇到一个bug,本来好的项目用xcode7一编译,tableView刷新出了问题 ,[tableView reloadData]无效,有一行cell明明改变了可是刷新不出来。 感受多是这个方法和某种新加的特性冲突了,猜想多是reloadData的操做被推迟到下一个RunLoop执行最终失效。

解决的方法是,注释[tableView reloadData],改用局部刷新,问题竟然就解决了。

Crayon Syntax Highlighter v2.7.1

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

1

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

[Format Time: 0.0006 seconds]

 

8、iPad适配Slide Over 和 Split View

iPad适配Slide Over 和 Split View,若想适配multi tasking特性,惟一的建议:

弃纯代码,改用storyboard、xib,纵观苹果WWDC全部Demo均是如此。

相关文章
相关标签/搜索