1、Xcode 專案屬性

  • Product Name

    • 軟體名稱、產品名稱、專案名稱
  • Organization Name

    • 公司名稱、組織名稱
  • Organization Identifier

    • 公司的唯一標識
    • 一般是公司域名的反寫,比如 com.baidu
  • Bundle Identifier

    • 軟體的唯一標識
    • 一般是 Organization Identifier + Product Name

2、App 應用間跳轉

2.1 應用跳轉原理

  • 相信從一個應用跳轉到另一個應用大家並不陌生,最常見的莫過於第三方登入,支付寶支付等等。這些東西大家都耳熟能詳,整合進來也很簡單,跟著第三方 sdk 整合文件一步步走下來就是了,通常 sdk 整合文件都需要你在工程中配置一堆堆的東西,但是配置的這些東西,你真的明白了嗎?比如下面這個,第三方登入或分享需要你配置的 URL Schemes:

  • 1、一些概念的補充

    • 協議:雙方互相遵守的一種規範,只有遵守共同的協議規範才能進行彼此的通訊。比如我們最熟悉的網路協議 http 協議。

    • URL:資源的路徑或地址。在 iOS 中有一個專門用於包裝資源路徑的類 NSURL。

    • 一個完整 URL 的組成

      	例如:http://123.0.0.1/path?page=100
      
      	http://		:協議型別
      123.0.0.1 :伺服器 ip 地址
      /path :資源存放的是路徑
      page=100 :請求的引數
    • NSURL 包裝一個完整地址

      	NSURL *url = [NSURL URLWithString:@"http://123.0.0.1/path?page=100"];
      
      	NSLog(@"scheme(協議):%@",url.scheme);
      NSLog(@"host(域名):%@",url.host);
      NSLog(@"path(路徑):%@",url.path);
      NSLog(@"query(引數):%@",url.query);
    • 列印結果如下

      	2015-12-02 14:50:38.442 TestDemo[5632:406869] scheme(協議):http
      2015-12-02 14:50:38.442 TestDemo[5632:406869] host(域名):123.0.0.1
      2015-12-02 14:50:38.442 TestDemo[5632:406869] path(路徑):/path
      2015-12-02 14:50:38.442 TestDemo[5632:406869] query(引數):page=100
  • 2、跳轉的原理

    • 一個應用能開啟另一個應用的必然條件是,另一個應用必須配置一個 scheme(協議),這樣應用程式才能根據協議找到需要開啟的應用。

    • 在 iOS 中,從一個 app 開啟另一個 app,這必然牽扯到兩個 app 之間的互動和通訊,像這種涉及到整個應用程式層面的事情,蘋果有一個專門的類來管理 UIApplication。在 iOS 中 UIApplication 其實就是代表著應用程式,這點從它的命名就可以窺之。而我們要開啟另一個應用程式,其實就是 UIApplication 下面這個的 API。

      • iOS 系統版本 < 10.0

        	通過應用程式開啟一個資源路徑
        @param url 資源路徑的地址
        @return 返回成功失敗的資訊 - (BOOL)openURL:(NSURL*)url;
      • iOS 系統版本 >= 10.0

        	通過應用程式開啟一個資源路徑
        @param url 資源路徑的地址
        @param options 附加引數
        @param completion 完成回撥 - (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options
        completionHandler:(void (^ __nullable)(BOOL success))completion;
        • UIApplication 的標頭檔案中列了一個可用在 options 字典中的 key: UIApplicationOpenURLOptionUniversalLinksOnly,可以設定布林值(預設是 NO),如果設定為 YES,則只能開啟應用裡配置好的有效通用連結。如果應用程式沒有配置,或者用於禁止開啟這個連結,則 completion handler 回撥裡的success 為 NO。
    • 它的一些我們非常熟悉的用法

      	// 撥打系統電話
      NSURL *url = [NSURL URLWithString:@"tel://10086"];
      [[UIApplication sharedApplication] openURL:url]; // 傳送系統簡訊
      NSURL *url = [NSURL URLWithString:@"sms://1383838438"];
      [[UIApplication sharedApplication] openURL:url];
    • 撥打系統電話、傳送系統簡訊其實就是應用間的跳轉。只要一執行以上兩個方法就會從你當前的應用跳轉到系統的撥打電話介面、傳送簡訊介面,撥打系統電話、傳送簡訊它倆就是手機本身自帶的兩個 app 應用。上面打電話和發簡訊的實現程式碼大同小異,唯一的區別是傳遞的 NSURL 引數不一樣,導致他們跳轉到不同的應用場景。我們再仔細分析下傳給它們的 NSURL 引數,就會發現 NSURL 的 scheme(協議)不一樣,打電話是 “tel://” 協議,發簡訊是 “sms://” 協議。

2.2 實現兩個 App 間的跳轉

  • 由 App:AppJump1 跳轉到 App:AppJump2。

  • 1、配置協議:在被跳轉的 App(如 AppJump2)的 TARGETS => Info => URL Types => URL Scheme 配置一個協議 scheme,這裡命名為 app2(名字可隨意配置,當然最好是英文並且跟你專案相關)

  • 2、配置協議白名單:在 iOS9.0 + 系統隱私控制裡禁止查詢裝置中已安裝的 App,所以在 iOS9.0 + 系統中要實現應用間跳轉還需要配置協議白名單。在發起跳轉的 App(如 AppJump1)的 Info.plist 檔案中增加一個 LSApplicationQueriesSchemes 欄位,把它設定為陣列型別,並配置需要跳轉的協議名單。

  • 3、在發起跳轉的 App(如 AppJump1)的執行跳轉方法中實現下面方法。

    	// app2 為在 App2 中設定的協議 scheme
    NSURL *url = [NSURL URLWithString:@"app2://"]; // 判斷能否跳轉到 App2
    if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳轉到 App2
    [[UIApplication sharedApplication] openURL:url]; } else {
    NSLog(@"沒有安裝應用");
    }

2.3 跳轉到指定介面

  • 想要跳轉到指定介面,必然是上一個 App 告訴下一個 App(被跳轉的 App)需要跳轉到哪個介面,而如何告訴它這裡便涉及到兩個 App 的通訊。我們從上面可以知道,兩個 App 之間的跳轉只需要配置一個 scheme,然後通過 UIApplication 呼叫它的物件方法 openURL: 即可實現,除此之外再也沒有實現任何程式碼了。而這之間是如何通訊的呢?答案依然是協議。

  • 1、在 "app2://" 協議後面的域名加上一些欄位用來標記需要跳轉的介面。

    	// 進入更多介面
    
    		// app2 為在 App2 中設定的協議 scheme
    NSURL *url = [NSURL URLWithString:@"app2://more"]; // 判斷能否跳轉到 App2
    if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳轉到 App2
    [[UIApplication sharedApplication] openURL:url]; } else {
    NSLog(@"沒有安裝應用");
    } // 進入設定介面 // app2 為在 App2 中設定的協議 scheme
    NSURL *url = [NSURL URLWithString:@"app2://set"]; // 判斷能否跳轉到 App2
    if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳轉到 App2
    [[UIApplication sharedApplication] openURL:url]; } else {
    NSLog(@"沒有安裝應用");
    }
  • 2、來到被跳轉的應用的 AppDelegate.m 檔案中,監聽其代理方法 application: handleOpenURL:,當應用程式將要被其他程式開啟時,會先執行此方法,並傳遞 url 過來。在 iOS9.0 + 上面的方法被廢棄了,改用這個方法 application: openURL: options:

    	// NS_DEPRECATED_IOS(2_0, 9_0)
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { if ([url.host isEqualToString:@"more"]) { // 到此做介面的跳轉,進入更多介面
    } if ([url.host isEqualToString:@"set"]) { // 到此做介面的跳轉,進入設定介面
    } return YES;
    } // NS_AVAILABLE_IOS(9_0)
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
    options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { if ([url.host isEqualToString:@"more"]) { // 到此做介面的跳轉,進入更多介面
    } if ([url.host isEqualToString:@"set"]) { // 到此做介面的跳轉,進入設定介面
    } return YES;
    }

2.4 常用 App 的跳轉

  • 在 iOS9.0 + 系統隱私控制裡禁止查詢裝置中已安裝的 App,所以在 iOS9.0 + 系統中要實現應用間跳轉還需要配置協議白名單。在發起跳轉的 App 的 Info.plist 檔案中增加一個 LSApplicationQueriesSchemes 欄位,把它設定為陣列型別,並配置需要跳轉的協議名單。

    	// 傳送系統簡訊
    NSURL *url = [NSURL URLWithString:@"sms://1383838438"];
    [[UIApplication sharedApplication] openURL:url];
  • 常用 App 相應的 URL 地址

    	URL 地址:
    
    	  	tel://電話號碼			// 打電話
    sms://電話號碼 // 發簡訊
    mailto://郵件地址 // 發郵件
    http://網址 // 呼叫瀏覽器 Safari
    https://網址 // 呼叫瀏覽器 Safari // 微信
    weixin://
    wechat:// // QQ
    mqq://
    mqqapi://
    mqqOpensdkSSoLogin://
    mqqopensdkapiV2://
    mqqopensdkapiV3://
    wtloginmqq2:// // 新浪微博
    sinaweibo://
    sinaweibohd://
    sinaweibosso://
    sinaweibohdsso://
    weibosdk://
    weibosdk2.5:// // 支付寶
    alipay://
    alipayshare://

2.5 系統設定介面的跳轉

  • 設定跳轉有三種方式,每一種的使用場景都不同。 並且你在跳轉到系統中自己應用下面設定的時候,你的應用要提前至少申請了某一個許可權,如通知,定位等,否則,會引起崩潰。

    • 方式一:prefs:root=某項服務

      • iOS 系統版本 < iOS10 , 只能跳轉到系統設定頁面。
      • 在 iOS10 系統上,不會跳轉。
    • 方式二:prefs:root=bundleID

      • iOS8 <= iOS 系統版本 < iOS10,支援跳轉到第三方應用的設定介面中。
      • 在 iOS7 系統上,僅僅只是跳轉到設定應用,不推薦使用。
      • 在 iOS10 系統上,不會跳轉。
    • 方式三:UIApplicationOpenSettingsURLString

      • iOS8 <= iOS 系統版本 < iOS10,支援跳轉到系統設定。
      • 在 iOS10 系統上,支援跳轉到自己應用設定,不支援跳轉到系統設定。
  • 1、在 iOS6 以下系統中。

    	// 開啟藍芽設定介面
    NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"];
    [[UIApplication sharedApplication] openURL:url];
  • 2、在 iOS6 至 iOS9 系統中,必須在 URL Types 中新增 prefs 才能開啟相應的設定介面。

    	// 開啟藍芽設定介面
    NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"];
    [[UIApplication sharedApplication] openURL:url]; // 開啟第三方應用設定介面,bundleID 為第三方應用的唯一標識,iOS8 iOS9 可用
    NSURL *url = [NSURL URLWithString:@"prefs:root=bundleID"];
    [[UIApplication sharedApplication] openURL:url];
  • 3、在 iOS10 系統中蘋果已經不允許 app 跳到各個系統設定頁面了,只能跳轉到自己應用設定頁面。

    	// 開啟自己應用設定介面
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
    • 將 prefs:root=某項服務 改為 app-Prefs:root=某項服務 也可以成功跳轉到系統設定頁面。

      	// 開啟藍芽設定介面
      NSURL *url = [NSURL URLWithString:@"app-Prefs:root=Bluetooth"];
      [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
  • 系統設定 相應的 URL 地址

    	URL 地址:
    
    		UIApplicationOpenSettingsURLString                       // 系統設定,支援 iOS8, iOS9, iOS10 系統
    
    		prefs:root=General&path=About                            // 關於本機
    prefs:root=General&path=ACCESSIBILITY // 輔助功能
    prefs:root=AIRPLANE_MODE
    prefs:root=General&path=AUTOLOCK
    prefs:root=General&path=USAGE/CELLULAR_USAGE
    prefs:root=Brightness
    prefs:root=Bluetooth // 藍芽設定
    prefs:root=General&path=DATE_AND_TIME
    prefs:root=DISPLAY&BRIGHTNESS // 顯示與亮度
    prefs:root=FACETIME
    prefs:root=General // 通用設定
    prefs:root=General&path=Keyboard
    prefs:root=CASTLE
    prefs:root=CASTLE&path=STORAGE_AND_BACKUP
    prefs:root=General&path=INTERNATIONAL
    prefs:root=LOCATION_SERVICES // 定位設定
    prefs:root=ACCOUNT_SETTINGS
    prefs:root=MOBILE_DATA_SETTINGS_ID // 蜂窩網路
    prefs:root=MUSIC // 音樂
    prefs:root=MUSIC&path=EQ
    prefs:root=MUSIC&path=VolumeLimit
    prefs:root=General&path=Network
    prefs:root=NIKE_PLUS_IPOD
    prefs:root=NOTES // Notes
    prefs:root=NOTIFICATIONS_ID // 系統通知
    prefs:root=Phone
    prefs:root=Photos // 照片與相機
    prefs:root=Privacy // 隱私設定
    prefs:root=General&path=ManagedConfigurationList
    prefs:root=General&path=Reset
    prefs:root=Sounds&path=Ringtone
    prefs:root=Safari // Safari
    prefs:root=General&path=Assistant
    prefs:root=Set // 系統設定
    prefs:root=Sounds // 聲音設定
    prefs:root=General&path=SOFTWARE_UPDATE_LINK
    prefs:root=STORE // APP Store
    prefs:root=TWITTER
    prefs:root=FACEBOOK
    prefs:root=General&path=USAGE prefs:root=VIDEO
    prefs:root=General&path=Network/VPN
    prefs:root=Wallpaper // 桌布設定
    prefs:root=WIFI // Wifi 設定
    prefs:root=INTERNET_TETHERING // 個人熱點

3、程式碼退出程式設定

	- (IBAction)outClick:(id)sender {

    	// 建立退出動畫
[UIView beginAnimations:@"exitApplication" context:nil]; [UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view.window cache:NO];
[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)]; self.view.window.bounds = CGRectMake(0, 0, 0, 0); [UIView commitAnimations];
} // 動畫完成後的響應事件
- (void)animationFinished:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { if ([animationID compare:@"exitApplication"] == 0) { // 退出 App
exit(0);
}
}

4、App 間的通訊方式

5、App 與外設間的通訊方式