當(dāng)您編寫執(zhí)行應(yīng)用擴(kuò)展程序任務(wù)的自定義代碼時(shí),您可能需要處理許多類型擴(kuò)展所共有的一些方案。使用本章中的代碼和建議來幫助您實(shí)施解決方案。
使用嵌入式框架共享代碼
您可以創(chuàng)建一個(gè)嵌入式框架,以在您的應(yīng)用擴(kuò)展程序及其包含應(yīng)用之間共享代碼。例如,如果您開發(fā)了一個(gè)圖像過濾器以用于您的照片編輯擴(kuò)展以及其包含的應(yīng)用程序,請(qǐng)將過濾器的代碼放在框架中并將框架嵌入到兩個(gè)目標(biāo)中。
確保您的嵌入式框架不包含應(yīng)用程序擴(kuò)展不可用的API,如某些API不適用于App Extensions中所述。如果您有一個(gè)包含此類API的自定義框架,您可以安全地從包含的應(yīng)用程序鏈接到它,但不能與應(yīng)用程序包含的擴(kuò)展共享該代碼。App Store拒絕鏈接到此類框架或以其他方式使用不可用API的任何應(yīng)用程序擴(kuò)展。
要配置應(yīng)用程序擴(kuò)展目標(biāo)以使用嵌入式框架,請(qǐng)將目標(biāo)的“僅限應(yīng)用程序擴(kuò)展安全API”構(gòu)建設(shè)置設(shè)置為“是”。如果不這樣做,Xcode會(huì)提醒您這樣做,方法是顯示警告“鏈接到dylib不安全,無法在應(yīng)用程序擴(kuò)展中使用”。
重要
鏈接到嵌入式框架的包含應(yīng)用程序必須包含arm64(iOS)或x86_64(OS X)體系結(jié)構(gòu)構(gòu)建設(shè)置,否則App Store將拒絕該應(yīng)用程序。(如創(chuàng)建應(yīng)用程序擴(kuò)展中所述,所有應(yīng)用程序擴(kuò)展必須包含相應(yīng)的64位體系結(jié)構(gòu)構(gòu)建設(shè)置。)
配置Xcode項(xiàng)目時(shí),必須在“復(fù)制文件”構(gòu)建階段選擇“框架”作為嵌入式框架的目標(biāo)。
重要
始終選擇“框架”作為“復(fù)制文件”構(gòu)建階段目標(biāo)。如果您改為選擇“SharedFramework”目的地,App Store將拒絕您的提交。
您可以為運(yùn)行iOS 7或更早版本的用戶提供包含應(yīng)用程序,但在iOS 8或更高版本中運(yùn)行時(shí)必須采取預(yù)防措施以安全地鏈接嵌入式框架。有關(guān)詳細(xì)信息,請(qǐng)閱讀將包含應(yīng)用程序部署到舊版iOS的內(nèi)容。
有關(guān)創(chuàng)建和使用嵌入式框架的更多信息,請(qǐng)觀看WWDC 2014視頻“構(gòu)建現(xiàn)代框架”,網(wǎng)址為https://developer.apple.com/videos/wwdc/2014。
與您的應(yīng)用程序共享數(shù)據(jù)
即使應(yīng)用程序擴(kuò)展包嵌套在其包含的應(yīng)用程序包中,運(yùn)行的應(yīng)用程序擴(kuò)展和包含應(yīng)用程序也無法直接訪問彼此的容器。
背景
要了解容器,閱讀關(guān)于iOS的文件系統(tǒng)中的文件系統(tǒng)編程指南。
但是,您可以啟用數(shù)據(jù)共享。例如,您可能希望允許您的應(yīng)用擴(kuò)展程序及其包含的應(yīng)用程序共享一組大量數(shù)據(jù),例如預(yù)渲染資產(chǎn)。
要啟用數(shù)據(jù)共享,請(qǐng)使用Xcode或Developer門戶為包含應(yīng)用及其包含的應(yīng)用擴(kuò)展啟用應(yīng)用組。接下來,在門戶中注冊(cè)應(yīng)用程序組,并指定要在包含的應(yīng)用程序中使用的應(yīng)用程序組。要了解如何使用應(yīng)用程序組,請(qǐng)參閱向應(yīng)用程序組添加應(yīng)用程序。
啟用應(yīng)用程序組后,應(yīng)用程序擴(kuò)展及其包含的應(yīng)用程序都可以使用[NSUserDefaults](https://developer.apple.com/library/archive/documentation/LegacyTechnologies/WebObjects/WebObjects_3.5/Reference/Frameworks/ObjC/Foundation/Classes/NSUserDefaults/Description.html#//apple_ref/occ/cl/NSUserDefaults)API共享對(duì)用戶首選項(xiàng)的訪問權(quán)限。要啟用此共享,請(qǐng)使用該[initWithSuiteName:](https://developer.apple.com/documentation/foundation/userdefaults/1409957-init)方法實(shí)例化新NSUserDefaults對(duì)象,并傳入共享組的標(biāo)識(shí)符。例如,共享擴(kuò)展程序可能會(huì)使用以下代碼更新用戶最近使用的共享帳戶:
// Create and share access to an NSUserDefaults objectNSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"com.example.domain.MyShareExtension"];// Use the shared user defaults object to update the user's account[mySharedDefaults setObject:theAccountName forKey:@"lastAccountName"];
圖4-1顯示了擴(kuò)展及其包含的應(yīng)用程序如何使用共享容器來共享數(shù)據(jù)。
圖4-1應(yīng)用程序擴(kuò)展的容器與其包含應(yīng)用程序的容器不同[圖片上傳中...(image-b6cfaa-1559570465434-0)]
重要
如果您的應(yīng)用擴(kuò)展程序使用[NSURLSession](https://developer.apple.com/documentation/foundation/urlsession)該類執(zhí)行后臺(tái)上載或下載,則必須設(shè)置共享容器,以便擴(kuò)展程序及其包含的應(yīng)用程序都可以訪問傳輸?shù)臄?shù)據(jù)。要了解如何在后臺(tái)執(zhí)行上載或下載,請(qǐng)參閱執(zhí)行上載和下載。
設(shè)置共享容器時(shí),包含應(yīng)用程序 - 以及允許參與數(shù)據(jù)共享的每個(gè)包含的應(yīng)用程序擴(kuò)展 - 都具有對(duì)共享容器的讀寫權(quán)限。要避免數(shù)據(jù)損壞,必須同步數(shù)據(jù)訪問。
使用Core Data,SQLite或Posix鎖來幫助協(xié)調(diào)共享容器中的數(shù)據(jù)訪問。
版本說明
在iOS 8.2及更高版本中,您也可以使用[UIDocument](https://developer.apple.com/documentation/uikit/uidocument)該類來協(xié)調(diào)共享數(shù)據(jù)訪問。
在iOS 9及更高版本中,您可以[NSFileCoordinator](https://developer.apple.com/documentation/foundation/nsfilecoordinator)直接使用該類進(jìn)行共享數(shù)據(jù)訪問,但是如果您這樣做,則必須[NSFilePresenter](https://developer.apple.com/documentation/foundation/nsfilepresenter)在應(yīng)用擴(kuò)展轉(zhuǎn)換為后臺(tái)時(shí)刪除對(duì)象。
訪問網(wǎng)頁
在共享擴(kuò)展(在兩個(gè)平臺(tái)上)和動(dòng)作擴(kuò)展(僅限iOS)中,您可以通過要求Safari運(yùn)行JavaScript文件并將結(jié)果返回到擴(kuò)展名來授予用戶訪問Web內(nèi)容的權(quán)限。您還可以在擴(kuò)展程序運(yùn)行之前(在兩個(gè)平臺(tái)上)使用JavaScript文件訪問網(wǎng)頁,或者在擴(kuò)展程序完成其任務(wù)后訪問或修改網(wǎng)頁(僅限iOS)。例如,共享擴(kuò)展可以幫助用戶共享來自網(wǎng)頁的內(nèi)容,或者iOS中的Action擴(kuò)展可以顯示用戶當(dāng)前網(wǎng)頁的翻譯。
要向您的應(yīng)用擴(kuò)展程序添加網(wǎng)頁訪問和操作,請(qǐng)執(zhí)行以下步驟:
創(chuàng)建一個(gè)包含名為的全局對(duì)象的JavaScript文件
ExtensionPreprocessingJS。將自定義JavaScript類的新實(shí)例分配給此對(duì)象。在
NSExtensionActivationRule應(yīng)用擴(kuò)展程序Info.plist文件的字典中,為NSExtensionActivationSupportsWebPageWithMaxCount密鑰指定非零值。(要了解有關(guān)激活規(guī)則字典的更多信息,請(qǐng)參閱為共享或操作擴(kuò)展聲明支持的數(shù)據(jù)類型。)當(dāng)您的應(yīng)用擴(kuò)展程序啟動(dòng)時(shí),使用
[NSItemProvider](https://developer.apple.com/documentation/foundation/nsitemprovider)該類來獲取執(zhí)行JavaScript文件返回的結(jié)果。在iOS應(yīng)用擴(kuò)展程序中,如果您希望Safari在您的擴(kuò)展程序完成其任務(wù)時(shí)修改網(wǎng)頁,請(qǐng)將值傳遞給JavaScript文件。(您也可以
NSItemProvider在此步驟中使用該類。)
要告訴Safari您的應(yīng)用擴(kuò)展程序包含JavaScript文件,請(qǐng)將該NSExtensionJavaScriptPreprocessingFile鍵添加到NSExtensionAttributes字典中。密鑰的值應(yīng)該是您希望Safari在擴(kuò)展開??始之前加載的文件。例如:
<key>NSExtensionAttributes</key><dict><key>NSExtensionJavaScriptPreprocessingFile</key><string>MyJavaScriptFile</string></dict>
在這兩個(gè)平臺(tái)上,您的自定義JavaScript類可以定義run()Safari在加載JavaScript文件后立即調(diào)用的函數(shù)。在該run()函數(shù)中,Safari提供了一個(gè)名為的參數(shù)completionFunction,您可以使用該參數(shù)以鍵值對(duì)象的形式將結(jié)果傳遞給您的應(yīng)用擴(kuò)展。
在iOS中,您還可以定義finalize()Safari completeRequestReturningItems:completion:在其任務(wù)結(jié)束時(shí)調(diào)用時(shí)調(diào)用的函數(shù)。一個(gè)finalize()函數(shù)可以使用的物品的延長(zhǎng)線在completeRequestReturningItems:completion:根據(jù)需要改變的網(wǎng)頁。
例如,如果您的iOS應(yīng)用擴(kuò)展程序在啟動(dòng)時(shí)需要網(wǎng)頁的基本URI,并且在停止時(shí)更改網(wǎng)頁的背景顏色,您可以編寫如清單4-1所示的JavaScript代碼。
清單4-1示例run()和finalize()函數(shù)
var MyExtensionJavaScriptClass = function() {};MyExtensionJavaScriptClass.prototype = {run: function(arguments) {// Pass the baseURI of the webpage to the extension.arguments.completionFunction({"baseURI": document.baseURI});},// Note that the finalize function is only available in iOS.finalize: function(arguments) {// arguments contains the value the extension provides in [NSExtensionContext completeRequestReturningItems:completion:].// In this example, the extension provides a color as a returning item.document.body.style.backgroundColor = arguments["bgColor"];}};// The JavaScript file must contain a global object named "ExtensionPreprocessingJS".var ExtensionPreprocessingJS = new MyExtensionJavaScriptClass;
在這兩個(gè)平臺(tái)上,您需要編寫代碼來處理從run()函數(shù)傳回的值。要獲取結(jié)果字典,請(qǐng)kUTTypePropertyList在NSItemProvider方法中指定類型標(biāo)識(shí)符[loadItemForTypeIdentifier:options:completionHandler:](https://developer.apple.com/documentation/foundation/nsitemprovider/1403900-loaditemfortypeidentifier)。在字典中,使用NSExtensionJavaScriptPreprocessingResultsKey鍵來獲取結(jié)果項(xiàng)。例如,要獲取清單4-1中的run()函數(shù)傳遞的基URI ,可以使用如下代碼:
[imageProvider loadItemForTypeIdentifier:kUTTypePropertyList options:nil completionHandler:^(NSDictionary *item, NSError *error) {NSDictionary *results = (NSDictionary *)item;NSString *baseURI = [[results objectForKey:NSExtensionJavaScriptPreprocessingResultsKey] objectForKey:@"baseURI"];}];
要finalize()在iOS應(yīng)用擴(kuò)展程序完成其任務(wù)時(shí)將值傳遞給函數(shù),請(qǐng)使用該NSItemProvider``initWithItem:typeIdentifier:方法將字符串中的值打包為[NSExtensionJavaScriptFinalizeArgumentKey](https://developer.apple.com/documentation/foundation/nsextensionjavascriptfinalizeargumentkey)密鑰。例如,要為清單4-1中的finalize()函數(shù)中使用的背景顏色指定紅色,您的擴(kuò)展可能會(huì)使用如下代碼:
NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];extensionItem.attachments = @[[[NSItemProvider alloc] initWithItem: @{NSExtensionJavaScriptFinalizeArgumentKey: @{@"bgColor":@"red"}} typeIdentifier:(NSString *)kUTTypePropertyList]];[[self extensionContext] completeRequestReturningItems:@[extensionItem] completion:nil];
執(zhí)行上傳和下載
用戶在應(yīng)用擴(kuò)展程序中完成任務(wù)后,會(huì)立即返回主機(jī)應(yīng)用。如果任務(wù)涉及可能冗長(zhǎng)的上載或下載,則需要確保在您的擴(kuò)展終止后它可以完成。要執(zhí)行上載或下載,請(qǐng)使用[NSURLSession](https://developer.apple.com/documentation/foundation/urlsession)該類創(chuàng)建URL會(huì)話并啟動(dòng)后臺(tái)上載或下載任務(wù)。
注意
回想一下,app擴(kuò)展無法使用其他類型的后臺(tái)任務(wù),例如支持VoIP或播放后臺(tái)音頻。有關(guān)更多信息,請(qǐng)參閱響應(yīng)主機(jī)應(yīng)用程序的請(qǐng)求。
在您的應(yīng)用擴(kuò)展程序啟動(dòng)上載或下載任務(wù)后,擴(kuò)展程序可以完成主機(jī)應(yīng)用程序的請(qǐng)求并終止,而不會(huì)影響任務(wù)的結(jié)果。要了解有關(guān)擴(kuò)展如何處理來自主機(jī)應(yīng)用程序的請(qǐng)求的詳細(xì)信息,請(qǐng)參閱響應(yīng)主機(jī)應(yīng)用程序的請(qǐng)求。在iOS中,如果后臺(tái)任務(wù)完成后您的擴(kuò)展程序未運(yùn)行,系統(tǒng)將在后臺(tái)啟動(dòng)您的包含應(yīng)用程序并調(diào)用[application:handleEventsForBackgroundURLSession:completionHandler:](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622941-application)應(yīng)用程序委托方法。
重要
如果您的應(yīng)用擴(kuò)展程序啟動(dòng)后臺(tái)[NSURLSession](https://developer.apple.com/documentation/foundation/urlsession)任務(wù),您還必須設(shè)置擴(kuò)展程序及其包含應(yīng)用程序都可以訪問的共享容器。使用類的[sharedContainerIdentifier](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1409450-sharedcontaineridentifier)屬性NSURLSessionConfiguration指定共享容器的標(biāo)識(shí)符,以便以后可以訪問它。
有關(guān)設(shè)置共享容器的指導(dǎo), 請(qǐng)參閱與您的應(yīng)用程序共享數(shù)據(jù)。
清單4-2顯示了配置URL會(huì)話并使用它來啟動(dòng)下載的一種方法。
清單4-2配置NSURLSession對(duì)象并開始下載的示例
NSURLSession *mySession = [self configureMySession];NSURL *url = [NSURL URLWithString:@"http://www.example.com/LargeFile.zip"];NSURLSessionTask *myTask = [mySession downloadTaskWithURL:url];[myTask resume];- (NSURLSession *) configureMySession {if (!mySession) {NSURLSessionConfiguration* config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@“com.mycompany.myapp.backgroundsession”];// To access the shared container you set up, use the sharedContainerIdentifier property on your configuration object.config.sharedContainerIdentifier = @“com.mycompany.myappgroupidentifier”;mySession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];}return mySession;}
由于一次只能有一個(gè)進(jìn)程可以使用后臺(tái)會(huì)話,因此您需要為包含應(yīng)用及其每個(gè)應(yīng)用擴(kuò)展創(chuàng)建不同的后臺(tái)會(huì)話。(每個(gè)后臺(tái)會(huì)話都應(yīng)該有一個(gè)唯一的標(biāo)識(shí)符。)建議您的包含應(yīng)用程序僅在后臺(tái)啟動(dòng)應(yīng)用程序時(shí)使用由其中一個(gè)擴(kuò)展創(chuàng)建的后臺(tái)會(huì)話來處理該擴(kuò)展的事件。如果您需要在包含應(yīng)用程序中執(zhí)行其他與網(wǎng)絡(luò)相關(guān)的任務(wù),請(qǐng)為它們創(chuàng)建不同的URL會(huì)話。
如果您需要在啟動(dòng)后臺(tái)URL會(huì)話之前完成主機(jī)應(yīng)用程序的請(qǐng)求,請(qǐng)確保創(chuàng)建和使用會(huì)話的代碼有效。在您的應(yīng)用擴(kuò)展程序調(diào)用[completeRequestReturningItems:completionHandler:](https://developer.apple.com/documentation/foundation/nsextensioncontext/1411301-completerequest)以告知主機(jī)應(yīng)用程序其請(qǐng)求已完成后,系統(tǒng)可以隨時(shí)終止您的擴(kuò)展程序。
聲明共享或操作擴(kuò)展的支持?jǐn)?shù)據(jù)類型
在您的“共享”或“操作”擴(kuò)展程序中,您可能可以使用某些類型的數(shù)據(jù),但不能處理其他類型的數(shù)據(jù)。要確保主機(jī)應(yīng)用僅在用戶選擇了您支持的類型的數(shù)據(jù)時(shí)才提供您的擴(kuò)展,請(qǐng)將該NSExtensionActivationRule密鑰添加到您的擴(kuò)展的Info.plist屬性列表文件中。您還可以使用此鍵指定擴(kuò)展程序可以處理的每種類型的最大項(xiàng)目數(shù)。
當(dāng)您的分機(jī)運(yùn)行時(shí),系統(tǒng)會(huì)將NSExtensionActivationRule密鑰的值與分機(jī)項(xiàng)[attachments](https://developer.apple.com/documentation/foundation/nsextensionitem/1416690-attachments)屬性中的信息進(jìn)行比較。有關(guān)可以使用此鍵的完整鍵列表,請(qǐng)參閱操作擴(kuò)展鍵。
例如,要聲明您的共享擴(kuò)展程序最多可以支持十個(gè)圖像,一個(gè)電影和一個(gè)網(wǎng)頁URL,您可以使用以下字典作為該NSExtensionAttributes鍵的值:
<key>NSExtensionAttributes</key><dict><key>NSExtensionActivationRule</key><dict><key>NSExtensionActivationSupportsImageWithMaxCount</key><integer>10</integer><key>NSExtensionActivationSupportsMovieWithMaxCount</key><integer>1</integer><key>NSExtensionActivationSupportsWebURLWithMaxCount</key><integer>1</integer></dict></dict>
如果您不支持特定數(shù)據(jù)類型,請(qǐng)使用0相應(yīng)鍵的值或從NSExtensionActivationRule字典中刪除鍵。
注意
如果您的共享或iOS操作擴(kuò)展程序需要訪問網(wǎng)頁,則必須包含NSExtensionActivationSupportsWebPageWithMaxCount非零值的密鑰。(要了解如何使用JavaScript從您的擴(kuò)展程序訪問網(wǎng)頁,請(qǐng)參閱訪問網(wǎng)頁。)
NSExtensionActivationRule字典中 的鍵足以滿足典型應(yīng)用擴(kuò)展的過濾需求。如果您需要執(zhí)行更復(fù)雜或更具體的過濾,例如區(qū)分public.url和public.image,則可以創(chuàng)建謂詞語句。然后,使用表示謂詞的裸字符串作為NSExtensionActivationRule鍵的值。(在運(yùn)行時(shí),系統(tǒng)將此字符串編譯為[NSPredicate](https://developer.apple.com/documentation/foundation/nspredicate)對(duì)象。)
例如,應(yīng)用擴(kuò)展程序項(xiàng)的attachments屬性可以指定PDF文件,如下所示:
{extensionItems = ({attachments = ({registeredTypeIdentifiers = ("com.adobe.pdf","public.file-url");});})}
要指定您的應(yīng)用擴(kuò)展程序只能處理一個(gè)PDF文件,您可以創(chuàng)建一個(gè)謂詞字符串,如下所示:
SUBQUERY (extensionItems,$extensionItem,SUBQUERY ($extensionItem.attachments,$attachment,ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.adobe.pdf").@count == $extensionItem.attachments.@count).@count == 1
以下是更復(fù)雜的謂詞語句的示例:
SUBQUERY (extensionItems,$extensionItem,SUBQUERY ($extensionItem.attachments,$attachment,ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.action-one" ||ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.action-two").@count == $extensionItem.attachments.@count).@count == 1
此語句遍歷一個(gè)[NSExtensionItem](https://developer.apple.com/documentation/foundation/nsextensionitem)對(duì)象數(shù)組,其次[attachments](https://developer.apple.com/documentation/foundation/nsextensionitem/1416690-attachments)是每個(gè)擴(kuò)展項(xiàng)中的數(shù)組。對(duì)于每個(gè)附件,謂詞評(píng)估附件中每個(gè)表示的統(tǒng)一類型標(biāo)識(shí)符(UTI)。當(dāng)附件表示UTI符合兩個(gè)不同的指定UTI中的任何一個(gè)(您在每個(gè)UTI-CONFORMS-TO操作員的右側(cè)看到)時(shí),收集該UTI以進(jìn)行最終比較測(cè)試。TRUE如果應(yīng)用程序擴(kuò)展名僅提供了一個(gè)支持UTI的擴(kuò)展項(xiàng)附件,則返回最后一行。
僅在開發(fā)期間,您可以使用TRUEPREDICATE常量(始終求值為true)作為存根謂詞語句,以在實(shí)現(xiàn)謂詞語句之前測(cè)試代碼路徑。
重要
在將包含應(yīng)用程序提交到App Store之前,請(qǐng)確保使用TRUEPREDICATE功能謂詞語句或NSExtensionActivationRule鍵替換存根謂詞的所有使用。如果您的包含應(yīng)用中的任何應(yīng)用擴(kuò)展程序包含該字符串TRUEPREDICATE,則該應(yīng)用將被拒絕。
要了解更多關(guān)于斷言語句的語法,請(qǐng)參閱謂詞格式化字符串的語法在謂詞編程指南。
將包含的應(yīng)用程序部署到iOS的舊版本
如果從包含的應(yīng)用程序鏈接到嵌入式框架,您仍然可以將其部署到8.0之前的iOS版本,即使這些版本中沒有嵌入式框架。
允許您執(zhí)行此操作的機(jī)制是dlopen命令,您可以使用該命令有條件地鏈接和加載框架包。您可以使用此命令替代您可以在Xcode General或Build Phases目標(biāo)編輯器中指定的構(gòu)建時(shí)鏈接。主要思想是僅在iOS 8.0或更高版本中運(yùn)行時(shí)將嵌入式框架鏈接到包含應(yīng)用程序。
您必須在有條件地加載框架包的代碼語句中使用Objective-C而不是Swift。您的應(yīng)用程序的其余部分可以用任何一種語言編寫,嵌入式框架本身也可以用任何一種語言編寫。
調(diào)用之后dlopen,使用以下類型的語句訪問嵌入式框架類:
MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];
重要
如果您的包含應(yīng)用目標(biāo)鏈接到嵌入式框架,它必須包含arm64架構(gòu),否則它將被App Store拒絕。
設(shè)置應(yīng)用擴(kuò)展Xcode項(xiàng)目以利用條件鏈接
-
對(duì)于每個(gè)包含的應(yīng)用擴(kuò)展程序,像往常一樣將部署目標(biāo)設(shè)置為iOS 8.0或更高版本。
在Xcode目標(biāo)編輯器的“常規(guī)”選項(xiàng)卡的“部署信息”部分中執(zhí)行此操作。
對(duì)于包含應(yīng)用程序,請(qǐng)將部署目標(biāo)設(shè)置為您要支持的最舊版本的iOS。
-
在您的包含應(yīng)用程序中,
dlopen使用該[systemVersion](https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion)方法在運(yùn)行時(shí)檢查iOS版本的條件下調(diào)用該命令。dlopen僅當(dāng)您的包含應(yīng)用程序在iOS 8.0或更高版本中運(yùn)行時(shí)才 調(diào)用該命令。進(jìn)行此調(diào)用時(shí),請(qǐng)務(wù)必使用Objective-C,而不是Swift。
某些iOS API通過dlopen命令使用嵌入式框架。您必須像dlopen直接調(diào)用一樣使用這些API 。這些API來自[CFBundleRef](https://developer.apple.com/documentation/corefoundation/cfbundle)opaque類型:
[CFBundleGetFunctionPointerForName](https://developer.apple.com/documentation/corefoundation/1537143-cfbundlegetfunctionpointerfornam)[CFBundleGetFunctionPointersforNames](https://developer.apple.com/documentation/corefoundation/1537109-cfbundlegetfunctionpointersforna)
從[NSBundle](https://developer.apple.com/library/archive/documentation/LegacyTechnologies/WebObjects/WebObjects_3.5/Reference/Frameworks/ObjC/Foundation/Classes/NSBundle/Description.html#//apple_ref/occ/cl/NSBundle)課堂上講:
[load](https://developer.apple.com/library/archive/documentation/LegacyTechnologies/WebObjects/WebObjects_3.5/Reference/Frameworks/ObjC/Foundation/Classes/NSBundle/Description.html#//apple_ref/occ/instm/NSBundle/load)[loadAndReturnError:](https://developer.apple.com/documentation/foundation/nsbundle/1411819-loadandreturnerror)[classNamed:](https://developer.apple.com/library/archive/documentation/LegacyTechnologies/WebObjects/WebObjects_3.5/Reference/Frameworks/ObjC/Foundation/Classes/NSBundle/Description.html#//apple_ref/occ/instm/NSBundle/classNamed:)
在您正在部署到8.0之前的iOS版本的應(yīng)用程序中,僅在運(yùn)行時(shí)檢查中調(diào)用這些API,以確保您在iOS 8.0或更高版本中運(yùn)行,并使用Objective-C調(diào)用這些API。