iOS7中容易被忽视的新特性

jopen 10年前
 
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地址不能再用来设别设备
 
iOS7中容易被忽视的新特性
现在仍可以使用这个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]; 
每种方法都适配一种特别的用法:
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. }]; 
你同时还要注意,如果你在获得用户的同意之前使用任何方法来使用麦克风的话,会引起iOS系统弹出以下警示栏:
iOS7中容易被忽视的新特性
 
好消息:性能提高以及被遗弃的功能
以上就是一些重要的更新,他们可能会让你现在的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; 
因为上面的方式很平常,有些人将它作为一个类增加到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绘制图片,忽略图片的颜色信息。 
 
renderingMode属性的默认值是UIImageRenderingModeAutomatic,即UIImage是否使用Tint Color取决于它显示的位置。其他情况可以看下面的图例
iOS7中容易被忽视的新特性
 
以下的代码说明了使用一个既定的rendering模式创建图片是多么简单:
    
  1. UIImage *img = [UIImage imageNamed:@"myimage"]; 
  2. img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 
 
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; 
 9.去掉了纹理颜色
iOS7中容易被忽视的新特性
 
纹理颜色?对,不再使用他们了。不能再创建可以展现纹理的颜色。根据UIInterface.h文件中的注释,-[UIColor groupTableViewBackgroundColor]应该是要在iOS6当中即被删除了,但是它仅仅只是不像之前那样返回纹理颜色了。然而,以 下的颜色在iOS7当中被删除了:
    
  1. + (UIColor *)viewFlipsideBackgroundColor; 
  2. + (UIColor *)scrollViewTexturedBackgroundColor; 
  3. + (UIColor *)underPageBackgroundColor; 
 
10.UIButtonTypeRoundRect被UIButtonTypeSystem取代了
iOS7中容易被忽视的新特性
 
在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;  
 
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. - (void)radioAccessChanged { 
  20.   NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology); 
  21.   
  22. @end 
注意:研究一下CTTelephonyNetworkInfo.h 文件来看看是否有其他无线网络类型的的字符串常量。如果设备没有连上的话,currentRadioAccessTechnology 则会返回nil。
 
13.通过iCloud同步用户设备的密码
iOS7以及Mavericks增加了iCloud Keychain来提供密码,以及iCloud中一些敏感数据的同步。开发者可以通过keychain中的kSecAttrSynchronizable key来遍历dictionary对象。
 
由于直接处理keychain比较难,封装库提供了一个简单的处理keychain的方法。SSKeychain封装库可能是最有名的的一个,作为一种福利,现在它支持在iCloud同步。
 
以下代码片段显示了如何使用SSKeychain:
    
  1. #import  
  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. - (NSString *)savedPassword:(NSError **)error { 
  12.     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
  13.     query.service = @"MyAwesomeService"
  14.     query.account = @"John Doe"
  15.     query.synchronizable = YES; 
  16.     query.password = nil; 
  17.     if ([query fetch:&error]) { 
  18.         return query.password; 
  19.     } 
  20.     return nil; 
不要忘记CocoaPods是快速便捷安装SSKeychian的好方法。
 
14.使用NSAttributedString显示HTML
在app中使用Webviews有时会让人非常沮丧,即使只是显示少量的HTMLneirong ,Webviews也会消耗大量的内容。现在iOS7让这些变得简单了,你可以从用少量代码在HTML文件中创建一个NSAttributedString,比如:
    
  1. NSString *html = @"Wow! Now iOS can create 

    NSAttributedString

     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.   
 
现在你可以在任意的UIKit对象上使用NSAttributedString 了,比如说是一个UILabel或是一个UITextField,见以下代码:
    
  1. #import  
  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. - (NSString *)savedPassword:(NSError **)error { 
  12.     SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; 
  13.     query.service = @"MyAwesomeService"
  14.     query.account = @"John Doe"
  15.     query.synchronizable = YES; 
  16.     query.password = nil; 
  17.     if ([query fetch:&error]) { 
  18.         return query.password; 
  19.     } 
  20.     return nil; 
  注意: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]; 
现在你估计在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; 
 
这些方法可以帮助你轻易的将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" 
 
如果你需要支持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 NSDataBase64Encoding 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; 
  
16.使用UIApplicationUserDidTakeScreenshotNotification来检查截图
 在iOS7之前,像Snapshot或是非死book 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]; 
 
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]; 
 
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 
 
以下是让键盘可以在滚动的时候消失需要设置的属性:
 
iOS7中容易被忽视的新特性
 
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.给UITextView增加了链接
现在在iOS添加你自己的推ter账户更加简单了,现在你可以给一个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; 
 
这样就可以让链接在文本中显示。然而,你也可以控制当链接被点击的时候会发生什么,实现这个可以使用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 
 
现在这些新功能就介绍完了。