iOS7开发中的新特性

    iOS7到如今已经发布了有一段时间了。相信你如今已经了解了它那些开创性的视觉设计,已经了解了它的新的API,好比说SpirteKit,UIKit Dynamics以及TextKit,做为开发者,也极可能已经在使用Xcode5进行开发了。
 
然而,它新颖以及备受争议的特性,让iOS7成为iOS系统史上最大的发布之一。除非你是那种用整晚的时间阅读iOS7更新内容的那种人,那么就可能会忽视掉一两个新的变化。
 
在本篇文章中咱们汇总了一份较完备的iOS7重要且有趣的新变化。如今让咱们一块儿来看看是否有一些新变化你之前没有注意到呢?
 
坏消息,好消息,以及很是好的消息
iOS7有一些坏消息,一些好消息,还有一些很是好的消息。
 
坏消息:iOS7中有一些可能会对app形成破坏性的变化,你必需要了解。若是你还不知道这些变化的话,那么你就须要好好看看他们了,由于当他们在iOS7上运行的时候可能会形成app崩溃!
 
好消息:有一些你熟悉的特性和API在iOS7中获得了优化——可是还有一些其余的特性被遗弃了。花点时间来看看这些变化,对你app的升级来讲是个很好的投资。
 
很是好的消息:iOS7的发布确实震动了手机开发世界,随着这个重大事件的发生,随之而来的也有一系列新功能,它们可能会给你现有app带来新特点,也可能成为未来开发的app创新的触发剂。
 
本篇文章搜罗了iOS7容易忽略的一些特色,将它们分为了以上三类。如下的列表,若是有感兴趣的内容能够直接跳过去看,也能够按照文章的顺序来了解全部的变化。
 
 坏消息:能够致使app崩溃的变化
1.已禁用-[UIDevice uniqueIdentifier]
2.UIPasteboard由共享变为沙盒化了
3.MAC地址不能再用来识别设备
4.iOS如今要求app如需使用麦克风,须要征得用户赞成
 
好消息:性能提升以及被遗弃的功能
5.-[NSArray firstObject]的实现
6.增长了instancetype
7.设置UIImage的渲染模式:UIImage.renderingMode
8.tintColor VS barTintColor
9.去掉了纹理颜色
10.UIButtonTypeRoundRect被UIButtonTypeSystem取代了
 
很是好的消息:新功能
11.检查无线路由是否可用
12.了解蜂窝网络
13.经过iCloud同步用户设备的密码
14.使用NSAttributedString显示HTML
15.使用原生的Base64
16.使用UIApplicationUserDidTakeScreenshotNotification来检查截图
17.实现多语言语音合成
18.使用了新的手势识别
19.使用UIScrollViewKeyboardDismissMode实现了Message app的行为
20.使用Core Image来检测眨眼以及微笑
21.给UITextView增长了连接
 
坏消息:能够致使app崩溃的变化
这个部分的变化你可能在了解iOS7的时候已经注意到了,可是你也许没有意识到这些变化的程度,以及它们如何可能会影响你的app。事实上这些变化都和用户隐私相关,而你应该知道对苹果来讲用户隐私有多么重要!
 
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地址不能再用来设别设备
 
如今仍可使用这个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]来做为你框架和应用的惟一标示符。坦白的来讲,应对这些变化也不是那么的难,见如下代码片断:
1 NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString]; 
2 NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; 
View Code

 

每种方法都适配一种特别的用法:
identifierForVendor对供应商来讲是惟一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,若是用户删除了这个供应商的app而后再从新安装的话,这个标识符就会不一致。
 
advertisingIdentifier会返回给在这个设备上全部软件供应商相同的 一个值,因此只能在广告的时候使用。这个值会由于不少状况而有所变化,好比说用户初始化设备的时候便会改变。
 
若是你想了解更多的信息,你能够看看 这篇文章
 
4.iOS如今要求app如需使用麦克风,须要征得用户赞成
之前若是app须要使用用户的位置,通信录,日历,提醒以及照片,接受推送消息,使用用户的社交网络的时候须要征得用户的赞成。如今在iOS7当中,使用麦克风也须要取得用户赞成了。若是用户不容许app使用麦克风的话,那么须要使用麦克风的app就不能接收不到任何声音。
 
如下的代码是用来查询用户是否容许app使用麦克风:
 1 //第一次调用这个方法的时候,系统会提示用户让他赞成你的app获取麦克风的数据 
 2 // 其余时候调用方法的时候,则不会提醒用户 
 3 // 而会传递以前的值来要求用户赞成 
 4 [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { 
 5     if (granted) { 
 6         // 用户赞成获取数据 
 7     } else { 
 8         // 能够显示一个提示框告诉用户这个app没有获得容许? 
 9     } 
10 }]; 
View Code

 

你同时还要注意,若是你在得到用户的赞成以前使用任何方法来使用麦克风的话,会引发iOS系统弹出如下警示栏:
 
好消息:性能提升以及被遗弃的功能
以上就是一些重要的更新,他们可能会让你如今的app崩溃。而后,还有一些变化可能会对你的app形成影响,可是你不会在第一时间发现这些变化。
 
5.-[NSArray firstObject]的实现
-[NSArray firstObject]多是Objective-C中被调用作多的API。在Open Radar上一个简单的调查显示有一些需求苹果已经作了记录。好消息是如今这些需求已经获得了解决。. firstObject的使用能够追溯到iOS4.0,可是那时仅仅是一个私有方法。在iOS7之前,工程师用下面的方式来使用它:
 
1 NSArray *arr = @[]; 
2 id item = [arr firstObject]; 
3 // 以前你须要作如下工做 
4 id item = [arr count] > 0 ? arr[0] : nil; 
View Code

 

由于上面的方式很日常,有些人将它做为一个类增长到NSArray中,而后建立他们本身的firstObject方法。在Github上作一个快速搜索你能够看到过去这种方式是有多么的经常使用。
 
 这个方法的问题是这个方法的名字必须是惟一的,不然的话这个方法所引起的问题没法预估。请确保检查你是否有任何自定义的代码在NSArray上实现了firstObject,若是有的话看看它是不是必须的,不是必须的话就把它所有移除。
 
6.增长了instancetype
instancetype让iOS7API变得更加难懂。苹果改变了大部分 initializer和简易构造函数(convenience constructors),用instancetype代替id做返回类型。可是这个instancetype是什么呢?
 
instancetype用来在声明一个方法时告诉编译器其返回类型,它表示返回调用该方法的类的对象。这比以前返回id的一般作法要好,编译器能够对返回类型作一些检查,若是出现错误,在编译时就能提醒你,而不是在程序运行时发生崩溃。同时,在调用子类方法时,使用它还能够省去对返回值的强制类型转换,编译器可以正确推断方法的返回值类型。
 
要说到instancetaype的缺点和优势吗?基本上,在任何可能的状况下均可以使用它。
 
若是须要更多关于instancetype的信息,你能够看看 这篇文章
 
  7.设置UIImage的渲染模式:UIImage.renderingMode
着色(Tint Color)是iOS7界面中的一个重大改变,你能够设置一个UIImage在渲染时是否使用当前视图的Tint Color。UIImage新增了一个只读属性:renderingMode,对应的还有一个新增方法:imageWithRenderingMode:,它使用UIImageRenderingMode枚举值来设置图片的renderingMode属性。该枚举中包含下列值:
1 UIImageRenderingModeAutomatic // 根据图片的使用环境和所处的绘图上下文自动调整渲染模式。 
2 UIImageRenderingModeAlwaysOriginal // 始终绘制图片原始状态,不使用Tint Color。 
3 UIImageRenderingModeAlwaysTemplate // 始终根据Tint Color绘制图片,忽略图片的颜色信息。 
View Code

 

 
renderingMode属性的默认值是UIImageRenderingModeAutomatic,即UIImage是否使用Tint Color取决于它显示的位置。其余状况能够看下面的图例
 
如下的代码说明了使用一个既定的rendering模式建立图片是多么简单:
1 UIImage *img = [UIImage imageNamed:@"myimage"]; 
2 img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 
View Code

 

 
8.tintcolor VS barTintColor
iOS7中你可使用一个给定的颜色,甚至是记入颜色主题来给整个app着色,帮助你的app脱颖而出。设置app的tint color很简答,只要使用UIView的新属性tintColor便可。
 
这个属性是否听上去很熟悉呢?应该很熟悉,有些类,好比说UINaviagtionBar,UISearchBar,UITabBar以及UIToolbar已经有了这么命名的属性。他们如今有了一个新的属性:barTintColor。
 
为了不使用新属性的时候犯错误,若是你的appp须要支持iOS6之前的系统的时候,请检查一下。
1 UINavigationBar *bar = self.navigationController.navigationBar; 
2 UIColor *color = [UIColor greenColor]; 
3 if ([bar respondsToSelector:@selector(setBarTintColor:)]) { // iOS 7+ 
4     bar.barTintColor = color; 
5 } else { // what year is this? 2012? 
6     bar.tintColor = color; 
7 } 
View Code

 

 9.去掉了纹理颜色
 
纹理颜色?对,再也不使用他们了。不能再建立能够展示纹理的颜色。根据UIInterface.h文件中的注释,-[UIColor groupTableViewBackgroundColor]应该是要在iOS6当中即被删除了,可是它仅仅只是不像以前那样返回纹理颜色了。然而,如下的颜色在iOS7当中被删除了:
1 + (UIColor *)viewFlipsideBackgroundColor; 
2 + (UIColor *)scrollViewTexturedBackgroundColor; 
3 + (UIColor *)underPageBackgroundColor; 
View Code

 

 
10.UIButtonTypeRoundRect被UIButtonTypeSystem取代了
 
在iOS开发刚开始就陪伴着你的老朋友如今也被删除了,它就是UIButtonTypeRoundRect ,被新的UIButtonTypeSystem取代了。
 
很是好的消息:新功能
若是每次iOS系统的发布都没有一些新的功能会是什么样子?这些新功能相信大部分开发者已经知道了,你可能会发现一些新颖的方式将它们整合到你的app中去!
 
11.检查无线路由是否可用
定制一个视频播放器的能力在iOS版本每次的发布中一直有所进步。好比说,在iOS6以前,你不能在MPVolumeView中改变AirPlay的icon。
 
在iOS7当中,你能够经过AirPlay,蓝牙或是其余的虚线机制了解是否有一个远程的设备可用。了解它的话,就可让你的app在恰当的时候作恰当的事,好比说,在没有远程设备的时候就不显示AirPlay的icon。
 
如下是新增长到MPVolumeView的新属性和推送
1 @property (nonatomic, readonly) BOOL wirelessRoutesAvailable; //  是否有设备能够链接的无线线路? 
2 @property (nonatomic, readonly) BOOL wirelessRouteActive; // 设备如今是否链接上了网络 
3 NSString *const MPVolumeViewWirelessRoutesAvailableDidChangeNotification; 
4 NSString *const MPVolumeViewWirelessRouteActiveDidChangeNotification;  
View Code

 

 
12.了解蜂窝网络
在iOS7以前,是使用Reachability来检测设备是否链接到WWAN或是Wifi的。iOS7在这个基础上更进了一步,它会告诉你的设备链接上的是那种蜂窝网络,好比说是Edge网络,HSDPA网络,或是LTE网络。告诉用户他们链接上的是哪一种网络能够优化用户体验,由于这样他们会知道网速如何,不会去请求须要高网速的网络请求。
 
这是CTTelephonyNetworkInfo的部分功能,它是CoreTelephony框架的一部分。iOS7还增长了currentRadioAccessTechnology属性和CTRadioAccessTechnologyDidChangeNotification到这个类。还有一些新的字符串常量来定义可能的值,好比说是CTRadioAccessTechnologyLTE。
 
如下代码告诉你在app delegate中如何使用这个新功能:
 1 @import CoreTelephony.CTTelephonyNetworkInfo; // new modules syntax! 
 2  @interface AppDelegate ()  
 3 // we need to keep a reference to the CTTelephonyNetworkInfo object, otherwise the notifications won't be fired! 
 4 @property (nonatomic, strong) CTTelephonyNetworkInfo *networkInfo; 
 5   @end 
 6   
 7 @implementation ViewController  
 8   
 9 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
10   // whatever stuff your method does... 
11   
12   self.networkInfo = [[CTTelephonyNetworkInfo alloc] init]; 
13   NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology); 
14   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:
15 CTRadioAccessTechnologyDidChangeNotification object:nil]; 
16   
17   // whatever stuff your method does... 
18 } 
19   
20 - (void)radioAccessChanged { 
21   NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology); 
22 } 
23   
24 @end 
View Code

 

注意:研究一下CTTelephonyNetworkInfo.h 文件来看看是否有其余无线网络类型的的字符串常量。若是设备没有连上的话,currentRadioAccessTechnology 则会返回nil。
 
13.经过iCloud同步用户设备的密码
iOS7以及Mavericks增长了iCloud Keychain来提供密码,以及iCloud中一些敏感数据的同步。开发者能够经过keychain中的kSecAttrSynchronizable key来遍历dictionary对象。
 
因为直接处理keychain比较难,封装库提供了一个简单的处理keychain的方法。SSKeychain封装库多是最有名的的一个,做为一种福利,如今它支持在iCloud同步。
 
如下代码片断显示了如何使用SSKeychain:
 1 #import <SSKeychain.h> 
 2   
 3 - (BOOL)saveCredentials:(NSError **)error { 
 4     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
 5     query.password = @"MySecretPassword"; 
 6     query.service = @"MyAwesomeService"; 
 7     query.account = @"John Doe"; 
 8     query.synchronizable = YES; 
 9     return [query save:&error]; 
10 } 
11   
12 - (NSString *)savedPassword:(NSError **)error { 
13     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
14     query.service = @"MyAwesomeService"; 
15     query.account = @"John Doe"; 
16     query.synchronizable = YES; 
17     query.password = nil; 
18     if ([query fetch:&error]) { 
19         return query.password; 
20     } 
21     return nil; 
22 } 
View Code

 

不要忘记CocoaPods是快速便捷安装SSKeychian的好方法。
 
14.使用NSAttributedString显示HTML
在app中使用Webviews有时会让人很是沮丧,即便只是显示少许的HTMLneirong ,Webviews也会消耗大量的内容。如今iOS7让这些变得简单了,你能够从用少许代码在HTML文件中建立一个NSAttributedString,好比:
1 NSString *html = @"<bold>Wow!</bold> Now <em>iOS</em> can create <h3>NSAttributedString</h3> from HTMLs!"; 
2 NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; 
3   
4 NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] 
5 options:options documentAttributes:nil error:nil]; 
6   
View Code

 

 
如今你能够在任意的UIKit对象上使用NSAttributedString 了,好比说是一个UILabel或是一个UITextField,见如下代码:
 1 #import <SSKeychain.h> 
 2   
 3 - (BOOL)saveCredentials:(NSError **)error { 
 4     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
 5     query.password = @"MySecretPassword"; 
 6     query.service = @"MyAwesomeService"; 
 7     query.account = @"John Doe"; 
 8     query.synchronizable = YES; 
 9     return [query save:&error]; 
10 } 
11   
12 - (NSString *)savedPassword:(NSError **)error { 
13     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
14     query.service = @"MyAwesomeService"; 
15     query.account = @"John Doe"; 
16     query.synchronizable = YES; 
17     query.password = nil; 
18     if ([query fetch:&error]) { 
19         return query.password; 
20     } 
21     return nil; 
View Code

 

  注意:NSHTMLTextDocumentType 只是NSDocumentTypeDocumentAttribute key一种可能的值。你还可使用NSPlainTextDocumentType,NSRTFTextDocumentType或是NSRTFDTextDocumentType。
 
 你还能够从NSAttributedString中建立一个HTML字符串,以下:
1 NSAttributedString *attrString; // from previous code 
2 NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; 
3   
4 NSData *htmlData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:options error:nil]; 
5 NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding]; 
View Code

 

如今你估计在app中会更多的使用HTML了。
 
15.使用原生的Base64
Base64是使用ASCII码显示二进制数据的一种流行方法。直到如今,开发者还不得不使用开源的工具来编码解码Base64的内容。
 
如今iOS7引入了如下四种新的NSData方法来操做Base64编码的数据:
 1 // From NSData.h 
 2   
 3 /* Create an NSData from a Base-64 encoded NSString using the given options. By default, returns nil when the input is not recognized
 4  as valid Base-64. 
 5 */ 
 6 - (id)initWithBase64EncodedString:(NSString *)base64String options:(NSDataBase64DecodingOptions)options; 
 7   
 8 /* Create a Base-64 encoded NSString from the receiver's contents using the given options. 
 9 */ 
10 - (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options; 
11   
12 /* Create an NSData from a Base-64, UTF-8 encoded NSData. By default, returns nil when the input is not recognized as valid Base-64. 
13 */ 
14 - (id)initWithBase64EncodedData:(NSData *)base64Data options:(NSDataBase64DecodingOptions)options; 
15   
16 /* Create a Base-64, UTF-8 encoded NSData from the receiver's contents using the given options. 
17 */ 
18 - (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options; 
View Code

 

 
这些方法能够帮助你轻易的将NSData对象转化为Base64,或者将Base64转化为NSData object。见如下的例子:
1  NSData* sampleData = [@"Some sample data" dataUsingEncoding:NSUTF8StringEncoding]; 
2   
3 NSString * base64String = [sampleData base64EncodedStringWithOptions:0]; 
4 NSLog(@"Base64-encoded string is %@", base64String); // prints "U29tZSBzYW1wbGUgZGF0YQ==" 
5   
6 NSData* dataFromString = [[NSData alloc] initWithBase64EncodedString:base64String options:0]; 
7 NSLog(@"String is %@",[NSString stringWithUTF8String:[dataFromString bytes]]); // prints "String is Some sample data" 
View Code

 

 
若是你须要支持iOS6或者更早之前的系统,你可使用如下两个方法:
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 
2 they may be used for applications targeting releases prior to OS X 10.9 and iOS 7.0. 
3 */ 
4 - (id)initWithBase64Encoding:(NSString *)base64String; 
5 - (NSString *)base64Encoding; 
View Code

 

  
16.使用UIApplicationUserDidTakeScreenshotNotification来检查截图
 在iOS7以前,像Snapshot或是Facebook Poke这样的app是使用一些很精巧的方法来检测用户是否有截图。然而,iOS7提供一个崭新的推送方法:UIApplicationUserDidTakeScreenshotNotification。只要像往常同样订阅便可知道何时截图了。
 
注意:UIApplicationUserDidTakeScreenshotNotification 将会在截图完成以后显示。如今在截图截取以前没法获得通知。但愿苹果会在iOS8当中增长UIApplicationUserWillTakeScreenshotNotification。
 
17.实现多语言语音合成
若是可让app说话会不会很好呢?iOS7加入了两个新类:AVSpeechSynthesizer 以及AVSpeechUtterance。这两个类能够给你的app发声。颇有意思不是吗?有多种语言可供选择——Siri不会说的语言也有,好比说巴西葡萄牙语。
 
使用这两个类给app提供语言合成的功能很是简单。AVSpeechUtterance 表明你想说什么,如何说。AVSpeechSynthesizer 用来发出这些声音,见如下代码片断:
1 AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc] init]; 
2 AVSpeechUtterance *utterance =  
3   [AVSpeechUtterance speechUtteranceWithString:@"Wow, I have such a nice voice!"]; 
4 utterance.rate = AVSpeechUtteranceMaximumSpeechRate / 4.0f; 
5 utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]; // defaults to your system language 
6 [synthesizer speakUtterance:utterance]; 
View Code

 

 
18.使用了新的UIScreenEdgePanGestureRecognizer 
UIScreenEdgePanGestureRecognizer 继承自UIPanGestureRecognizer ,它可让你从屏幕边界便可检测手势。
 
使用新的手势识别器很简单,见如下:
1 UIScreenEdgePanGestureRecognizer *recognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:
2 @selector(handleScreenEdgeRecognizer:)]; 
3 recognizer.edges = UIRectEdgeLeft; // accept gestures that start from the left; we're probably building another hamburger menu! 
4 [self.view addGestureRecognizer:recognizer]; 
View Code

 

 
19.使用UIScrollViewKeyboardDismissMode实现了Message app的行为
像Messages app同样在滚动的时候可让键盘消失是一种很是好的体验。然而,将这种行为整合到你的app很难。幸运的是,苹果给UIScrollView添加了一个很好用的属性keyboardDismissMode,这样能够方便不少。
 
如今仅仅只须要在Storyboard中改变一个简单的属性,或者增长一行代码,你的app能够和办到和Messages app同样的事情了。
 
这个属性使用了新的UIScrollViewKeyboardDismissMode enum枚举类型。这个enum枚举类型可能的值以下:
1 UIScrollViewKeyboardDismissModeNone        // the keyboard is not dismissed automatically when scrolling 
2 UIScrollViewKeyboardDismissModeOnDrag      // dismisses the keyboard when a drag begins 
3 UIScrollViewKeyboardDismissModeInteractive // the keyboard follows the dragging touch off screen, and may be
4  pulled upward again to cancel the dismiss 
View Code

 

 
如下是让键盘能够在滚动的时候消失须要设置的属性:
 
 
20.使用Core Image来检测眨眼以及微笑
iOS给Core Image增长了两种人脸检测功能:CIDetectorEyeBlink以及CIDetectorSmile。这也就是说你如今能够在照片中检测微笑以及眨眼。
 
如下是在app中使用它的方法:
 1 UIImage *image = [UIImage imageNamed:@"myImage"]; 
 2 CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace 
 3                                           context:nil 
 4                                           options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}]; 
 5   
 6 NSDictionary *options = @{ CIDetectorSmile: @YES, CIDetectorEyeBlink: @YES }; 
 7   
 8 NSArray *features = [detector featuresInImage:image.CIImage options:options]; 
 9   
10 for (CIFaceFeature *feature in features) { 
11     NSLog(@"Bounds: %@", NSStringFromCGRect(feature.bounds)); 
12   
13     if (feature.hasSmile) { 
14     NSLog(@"Nice smile!"); 
15     } else { 
16     NSLog(@"Why so serious?"); 
17     } 
18     if (feature.leftEyeClosed || feature.rightEyeClosed) { 
19     NSLog(@"Open your eyes!"); 
20     } 
21 } 
View Code

 

21.给UITextView增长了连接
如今在iOS添加你本身的Twitter帐户更加简单了,如今你能够给一个NSAttributedString增长连接了,而后当它被点击的时候唤起一个定制的action。
 
首先,建立一个NSAttributedString而后增长给它增长一个NSLinkAttributeName 属性,见如下:
 1 NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"This is an example by @marcelofabri_"]; 
 2 [attributedString addAttribute:NSLinkAttributeName 
 3                          value:@"username://marcelofabri_" 
 4                          range:[[attributedString string] rangeOfString:@"@marcelofabri_"]]; 
 5   
 6   
 7 NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor], 
 8                                  NSUnderlineColorAttributeName: [UIColor lightGrayColor], 
 9                                  NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)}; 
10   
11 // assume that textView is a UITextView previously created (either by code or Interface Builder) 
12 textView.linkTextAttributes = linkAttributes; // customizes the appearance of links 
13 textView.attributedText = attributedString; 
14 textView.delegate = self; 
View Code

 

 
这样就可让连接在文本中显示。然而,你也能够控制当连接被点击的时候会发生什么,实现这个可使用UITextViewDelegate协议的新的shouldInteractWithURL方法,就像这样:
1 - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { 
2     if ([[URL scheme] isEqualToString:@"username"]) { 
3         NSString *username = [URL host];  
4         // do something with this username 
5         // ... 
6         return NO; 
7     } 
8     return YES; // let the system open this URL 
9 } 
View Code

 

 
如今这些新功能就介绍完了。
相关文章
相关标签/搜索