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]; 
每種方法都適配一種特別的用法:
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系統彈出以下警示欄:
 
好消息:性能提高以及被遺棄的功能
以上就是一些重要的更新,他們可能會讓你現在的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取決於它顯示的位置。其他情況可以看下面的圖例
 
以下的代碼說明了使用一個既定的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.去掉了紋理顏色
 
紋理顏色?對,不再使用他們了。不能再創建可以展現紋理的顏色。根據UIInterface.h文件中的註釋,-[UIColor groupTableViewBackgroundColor]應該是要在iOS6當中即被刪除了,但是它僅僅只是不像之前那樣返回紋理顏色了。然而,以下的顏色在iOS7當中被刪除了:
  1. + (UIColor *)viewFlipsideBackgroundColor; 
  2. + (UIColor *)scrollViewTexturedBackgroundColor; 
  3. + (UIColor *)underPageBackgroundColor; 
 
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;  
 
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 <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. - (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 = @"<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.   
 
現在你可以在任意的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. - (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 <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; 
  
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]; 
 
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 
 
以下是讓鍵盤可以在滾動的時候消失需要設置的屬性:
 
 
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添加你自己的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; 
 
這樣就可以讓鏈接在文本中顯示。然而,你也可以控制當鏈接被點擊的時候會發生什麼,實現這個可以使用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 
 
現在這些新功能就介紹完了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章