[文檔翻譯]AppExtension編程指南:擴(kuò)展基礎(chǔ)4

App Extension Programming Guide-App Extension Essentials

AppExtension編程指南:擴(kuò)展基礎(chǔ)4

Handling Common Scenarios
常見問題的處理方案

翻譯自蘋果官方文檔 App Extension Programming Guide--Handling Common Scenarios

常見問題的處理方案

當(dāng)編寫自定義代碼以執(zhí)行app擴(kuò)展任務(wù)時专挪,你可能需要處理一些其他多種類型擴(kuò)展也會出現(xiàn)的情況。在這一章節(jié)中忆绰,我們將幫助你如何應(yīng)對和處理這些常見的問題恰力。

使用內(nèi)嵌框架共享代碼

你可以創(chuàng)建一個內(nèi)嵌框架,用于在應(yīng)用擴(kuò)展和它的主應(yīng)用程序(containing app)之間共享代碼陡蝇。比如痊臭,你在照片編輯擴(kuò)展中開發(fā)了圖片濾鏡功能,那么同時該擴(kuò)展的主應(yīng)用程序containing app也有這個功能登夫,那么你可以將實(shí)現(xiàn)該功能的代碼封裝成一個框架广匙,并在擴(kuò)展target和主應(yīng)用程序target中嵌入這個框架。

你要確保你創(chuàng)建的內(nèi)嵌框架不包含應(yīng)用擴(kuò)展不能使用的API恼策。這類API一般使用unavailability宏來標(biāo)記鸦致,比如像 NS_EXTENSION_UNAVAILABLE

如果你創(chuàng)建的內(nèi)嵌框架中包含應(yīng)用擴(kuò)展不能使用的API涣楷,你可將其安全地Link到containing app分唾,它可以正常使用框架中的API,但是不能與應(yīng)用擴(kuò)展共享代碼(譯者注:也就是應(yīng)用擴(kuò)展不能使用該框架提供的所有API狮斗,繼而無法做到代碼共享)绽乔。如果你上傳App Store的應(yīng)用擴(kuò)展中有這種框架,或者其他部分使用了不可用的API情龄,那么審核時會被拒絕迄汛。

如果我們要想應(yīng)用擴(kuò)展使用內(nèi)嵌框架,那么首先要配置一下骤视。將target的Require Only App-Extension-Safe API選項(xiàng)設(shè)置為Yes鞍爱。如果你不這樣設(shè)置,那么Xcode會向你提示警告:linking against dylib not safe for use in application extensions专酗。

重要提示:如果containing app要鏈接至內(nèi)嵌框架睹逃,那么必須要支持arm64架構(gòu),否則在上傳App Store時會被拒絕祷肯。(如“創(chuàng)建應(yīng)用擴(kuò)展”章節(jié)中介紹的沉填,所有應(yīng)用擴(kuò)展都要支持arm64架構(gòu)。)

在配置配置Xcode項(xiàng)目時佑笋,必須在Copy Files編譯階段選擇“Frameworks”作為內(nèi)嵌框架的目標(biāo)翼闹。

重要提示:我們通常要選擇 Frameworks 作為 Copy Files 編譯階段目標(biāo)。如果你將其設(shè)置為 SharedFramework蒋纬,那么上傳App Store時會被拒絕的猎荠。

你可以讓containing app支持iOS7或更早的版本坚弱,但當(dāng)在iOS8或更新的版本中運(yùn)行時,要特別注意內(nèi)嵌框架的安全性关摇。詳細(xì)內(nèi)容可以參閱 Deploying a Containing App to Older Versions of iOS荒叶。

有關(guān)創(chuàng)建和使用內(nèi)嵌框架的更多內(nèi)容,請觀看WWDC 2014的視頻“Building Modern Frameworks”输虱。

與Containing App共享數(shù)據(jù)

應(yīng)用擴(kuò)展和它的containing app的安全域是有區(qū)別的些楣。即便擴(kuò)展包是嵌套在containing app包中的。默認(rèn)情況下宪睹,應(yīng)用擴(kuò)展和containing app是不能直接訪問對方的容器的愁茁。

BACKGROUND
要了解容器,閱讀 About the iOS File System 中的 File System Programming Guid.

不過你可以通過數(shù)據(jù)共享來實(shí)現(xiàn)這個愿望亭病。比如埋市,你希望應(yīng)用擴(kuò)展和它的containing app共享一個單一的大數(shù)據(jù)集。比如prerendered assets命贴。

要實(shí)現(xiàn)數(shù)據(jù)共享,我們要使用Xcode或者開發(fā)者門戶網(wǎng)站允許應(yīng)用擴(kuò)展和它的containing app成為一個應(yīng)用組食听,然后在開發(fā)者門戶網(wǎng)站中注冊應(yīng)用組胸蛛,并指明在containing app中使用該應(yīng)用組。關(guān)于應(yīng)用組的知識請查閱 Entitlement Key Reference 文檔的 Adding an App to an App Group 章節(jié)樱报。

當(dāng)你設(shè)置好應(yīng)用組后葬项,應(yīng)用擴(kuò)展和它的containing app就可以通過 NSUserDefaults API共享訪問用戶的信息。我們可以使用 initWithSuiteName: 方法實(shí)例化一個 NSUserDefaults 對象迹蛤,然后傳入共享組的標(biāo)示符民珍。比如一個共享擴(kuò)展,它或許會更新用戶最近經(jīng)常使用的共享賬號盗飒,那么我們可以這樣來寫:

// Create and share access to an NSUserDefaults object. 
NSUserDefaults *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"]; 

下圖向我們展示了應(yīng)用擴(kuò)展和它的containing app是如何通過共享容器實(shí)現(xiàn)數(shù)據(jù)共享的.

Figure 4-1應(yīng)用擴(kuò)展的容器與其containing app的容器是不同的嚷量。

image

重要提示:如果你的應(yīng)用擴(kuò)展使用NSURLSession類執(zhí)行后臺的上傳下載任務(wù)時,你必須要設(shè)置一個共享容器逆趣,這樣擴(kuò)展和containing app就可以訪問到轉(zhuǎn)換傳輸?shù)臄?shù)據(jù)蝶溶。后臺上傳下載的更多知識請參閱 Performing Uploads and Downloads。

如果你設(shè)置了共享容器宣渗,那么containing app和它包含的允許參與數(shù)據(jù)分享的擴(kuò)展就可以對共享容器里的內(nèi)容進(jìn)行讀寫操作了抖所。同時你還必須要對數(shù)據(jù)的操作進(jìn)行同步,以避免數(shù)據(jù)損壞或出錯痕囱。使用UIDocument類田轧、Core Data或者SQLite可以幫你可以讓用戶通過要求Safari運(yùn)行JS文件來訪問網(wǎng)絡(luò)內(nèi)容,并將結(jié)果返回到擴(kuò)展鞍恢。

版本說明
在iOS 8.2及更高版本中傻粘,您也可以使用UIDocument該類來協(xié)調(diào)共享數(shù)據(jù)訪問每窖。
在iOS 9及更高版本中,您可以NSFileCoordinator直接使用該類進(jìn)行共享數(shù)據(jù)訪問抹腿,但是如果您這樣做岛请,則必須NSFilePresenter在應(yīng)用擴(kuò)展轉(zhuǎn)換為后臺時刪除對象。

訪問網(wǎng)頁

在分享擴(kuò)展(iOS與OS X平臺)和Action擴(kuò)展(iOS平臺)中警绩,一般都允許用戶使用Safari瀏覽器訪問網(wǎng)頁并通過執(zhí)行JavaScript腳本崇败,并將結(jié)果返回到擴(kuò)展中。你也可以在你的擴(kuò)展運(yùn)行之前(適用于兩個平臺)或執(zhí)行完任務(wù)之后(僅適用于iOS平臺)通過JavaScript文件修改網(wǎng)頁內(nèi)容肩祥。比如分享擴(kuò)展后室,它可以幫助用戶分享網(wǎng)頁上的內(nèi)容,或者iOS上的Action擴(kuò)展可能會顯示當(dāng)前網(wǎng)頁的指定翻譯內(nèi)容混狠。

如果想添加網(wǎng)頁訪問和操作應(yīng)用擴(kuò)展岸霹,那么需要遵循下面幾個步驟:
1.創(chuàng)建一個JavaScript文件,并申明一個全局對象将饺,命名為 ExtensionPreprocessingJS贡避,并為該對象分配一個新的自定義JavaScript類的實(shí)例。
2.在應(yīng)用擴(kuò)展的屬性列表文件中添加關(guān)鍵字 NSExtensionJavaScriptPreprocessingFile予弧,給 Safari 瀏覽器指明使用哪個 JavaScript 文件刮吧。
3.在NSExtensionActivationRule字典中,將NSExtensionActivationSupportsWebURLWithMaxCount 賦值一個非零的值掖蛤。(更多關(guān)于 NSExtensionActivationRule 字典的知識請參閱 Declaring Supported Data Types for a Share or Action Extension杀捻。)
4.當(dāng)你的應(yīng)用擴(kuò)展開始運(yùn)行時,使用NSItemProvider類獲得運(yùn)行JavaScript文件所返回的結(jié)果蚓庭。
5.在iOS系統(tǒng)的應(yīng)用擴(kuò)展中致讥,如果你希望Safari在擴(kuò)展執(zhí)行完任務(wù)后更新網(wǎng)頁,那么你要向JavaScript文件中傳入值器赞。(在這一步中也使用NSItemProvider類垢袱。)

為了告知Safari你的應(yīng)用擴(kuò)展中包含一個JavaScript文件,你需要在應(yīng)用擴(kuò)展的Info.plist文件中拳魁,向NSExtensionAttributes字典添加NSExtensionJavaScriptPreprocessingFile關(guān)鍵字來指明你的JavaScript文件惶桐。這個鍵的值就是你希望當(dāng)你的應(yīng)用擴(kuò)展運(yùn)行前,Safari要加載的JavaScript文件的名稱潘懊。比如:

<key>NSExtensionAttributes</key>
        <dict>
            <key>NSExtensionJavaScriptPreprocessingFile</key>
            <string>MyJavaScriptFile</string> <!-- Do not include the ".js" filename extension -->
        </dict>

在iOS和OS X平臺中姚糊,在你自定義的JavaScript類中可以定義一個run()函數(shù),該函數(shù)就是Safari加載JavaScript文件的入口授舟。在run()函數(shù)中救恨,Safari提供了一個名為completionFunction的參數(shù),你可以使用鍵值對象的形式將結(jié)果傳給應(yīng)用擴(kuò)展释树。

在iOS平臺中肠槽,你還可以定義一個finalize()函數(shù)擎淤,當(dāng)應(yīng)用擴(kuò)展在任務(wù)結(jié)束階段調(diào)用completeRequestReturningItems:expirationHandler:completion:方法時Safari會調(diào)用finalize()函數(shù)。在該函數(shù)中秸仙,可以通過向completeRequestReturningItems:expirationHandler:completion:方法傳值官卡,來改變網(wǎng)頁內(nèi)容弟跑。

比如吨拍,你的iOS應(yīng)用擴(kuò)展需要基于一個網(wǎng)頁URI啟動夭织,并且當(dāng)它結(jié)束運(yùn)行時改變網(wǎng)頁的背景色,那么你需要這樣寫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;

在iOS和OS X平臺中捞蛋,你需要編寫代碼來處理run()函數(shù)返回的值孝冒,為獲取到字典中的值,我們需要指定kUTTypePropertyList類型作為標(biāo)示符傳入NSItemProvider類的 loadItemForTypeIdentifier:options:completionHandler:方法拟杉。在該字典中使用 NSExtensionJavaScriptPreprocessingResultsKey作為key來取值庄涡。比如下面例子中我們想要獲取將 URI 傳入 run()的返回值:

[imageProvider loadItemForTypeIdentifier:kUTTypePropertyList options:nil completionHandler:^(NSDictionary *item, NSError *error) {
    NSDictionary *results = (NSDictionary *)item;
        NSString *baseURI = [[results objectForKey:NSExtensionJavaScriptPreprocessingResultsKey] objectForKey:@"baseURI"];
    }];

finalize() 函數(shù)是在當(dāng)應(yīng)用擴(kuò)展執(zhí)行完任務(wù)后傳參并調(diào)用的,創(chuàng)建一個含有我們需要處理的值的字典搬设,然后用NSItemProviderinitWithItem:typeIdentifier:方法來封裝該字典穴店。比如當(dāng)擴(kuò)展執(zhí)行完任務(wù)后我們想讓網(wǎng)頁變?yōu)榧t色,我們可以這樣寫:

NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
    extensionItem.attachments = @[[[NSItemProvider alloc] initWithItem: @{NSExtensionJavaScriptFinalizeArgumentKey: @{@"bgColor":@"red"}} typeIdentifier:(NSString *)kUTTypePropertyList]];
    [[self extensionContext] completeRequestReturningItems:@[extensionItem] completion:nil];
 

執(zhí)行上傳下載任務(wù)

用戶一般的操作習(xí)慣都傾向于當(dāng)使用你的應(yīng)用擴(kuò)展完成某個任務(wù)后拿穴,可以將結(jié)果立即反饋在使用擴(kuò)展的應(yīng)用中迹鹅。如果一個擴(kuò)展要處理的任務(wù)包含較長時間的上傳下載操作時,你要確保當(dāng)你的應(yīng)用擴(kuò)展關(guān)閉后能繼續(xù)完成該任務(wù)贞言。為實(shí)現(xiàn)這個功能,我們需要使用NSURLSession類創(chuàng)建一個URL會話并創(chuàng)建后臺的上傳下載任務(wù)阀蒂。

提示:你可以回想一下其他類型的后臺任務(wù)该窗,比如后臺支持VoIP、后臺播放音樂蚤霞,這些是不能用應(yīng)用擴(kuò)展去實(shí)現(xiàn)的酗失。更多信息請參閱Respond to the Host App’s Request。

當(dāng)你的應(yīng)用擴(kuò)展準(zhǔn)備好上傳下載任務(wù)后昧绣,擴(kuò)展會完成調(diào)用它的應(yīng)用發(fā)出的請求规肴,并在不影響上傳下載任務(wù)的前提下終止擴(kuò)展。更多關(guān)于擴(kuò)展處理載體應(yīng)用請求的知識請參閱Respond to the Host App’s Request夜畴。在iOS系統(tǒng)中拖刃,如果你的應(yīng)用擴(kuò)展在執(zhí)行完后臺任務(wù)時并沒有在運(yùn)行,那么系統(tǒng)會自動在后臺運(yùn)行擴(kuò)展的載體應(yīng)用贪绘,并調(diào)用application:handleEventsForBackgroundURLSession:completionHandler: 代理方法兑牡。

重要提示:如果你的應(yīng)用擴(kuò)展在后臺創(chuàng)建了 NSURLSession 任務(wù),那么你必須要設(shè)置一個共享容器税灌,以確保擴(kuò)展和載體應(yīng)用實(shí)現(xiàn)數(shù)據(jù)共享均函。我們可以在 NSURLSessionConfiguration 類中使用sharedContainerIdentifier屬性來指定一個共享容器的標(biāo)示符亿虽,然后我們就可以通過該標(biāo)示符獲取到共享容器。請參閱 Sharing Data with Your Containing App 文檔來設(shè)置共享容器苞也。

下面的例子展示了如何配置一個URL會話洛勉,并創(chuàng)建一個下載任務(wù):

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;
}

因?yàn)樵趩挝粫r間內(nèi)只能由一個進(jìn)程使用后臺會話,所以你需要為載體應(yīng)用中的所有擴(kuò)展創(chuàng)建不同的后臺會話(每個后臺會話都要有一個唯一的標(biāo)示符)如迟。在這里我們建議當(dāng)載體應(yīng)用在后臺處理擴(kuò)展的任務(wù)時收毫,只使用一個該擴(kuò)展創(chuàng)建的后臺會話。如果你要執(zhí)行其他的網(wǎng)絡(luò)相關(guān)的任務(wù)氓涣,那么就要創(chuàng)建相應(yīng)的URL會話牛哺。

如果你需要在后臺創(chuàng)建URL會話之前完成載體應(yīng)用的請求,那么要確保創(chuàng)建和使用會話的代碼是有效可執(zhí)行的劳吠。當(dāng)你的擴(kuò)展調(diào)用 completeRequestReturningItems:completionHandler: 方法告知主叫應(yīng)用已經(jīng)完成相關(guān)請求后引润,系統(tǒng)就可以隨時終止你的應(yīng)用擴(kuò)展。

為分享和Action擴(kuò)展申明支持的數(shù)據(jù)類型

在你的分享或Action擴(kuò)展中痒玩,在它們的工作中可能會使用到一些數(shù)據(jù)淳附,并且這些數(shù)據(jù)的類型各不相同。為了確保只有當(dāng)用戶在載體應(yīng)用中選擇了你的擴(kuò)展支持的數(shù)據(jù)類型時蠢古,才會展示你的擴(kuò)展功能奴曙。你需要在擴(kuò)展的Info.plist屬性列表文件中添加 NSExtensionActivationRule 關(guān)鍵字。你也可以使用該關(guān)鍵字指定擴(kuò)展處理每種類型的最大數(shù)目草讶。當(dāng)你的應(yīng)用擴(kuò)展運(yùn)行時洽糟,系統(tǒng)會將NSExtensionActivationRule鍵的值與擴(kuò)展項(xiàng)的attachments屬性中的信息進(jìn)行比較。關(guān)于 NSExtensionActivationRule 關(guān)鍵字的詳細(xì)信息可以參閱 Action Extension Keys文檔中的 Information Property List Key Reference 章節(jié)堕战。

比如坤溃,你可以申明你的分享擴(kuò)展支持最多處理10張圖片,一部影片和一個網(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ù)類型薪介,那么你可以將該類型的值設(shè)置為0,或者在 NSExtensionActivationRule 中不添加該類型即可越驻。

注意:如果你的分享擴(kuò)展或iOS中的Action擴(kuò)展需要訪問網(wǎng)頁汁政,那你必須要確保 NSExtensionActivationSupportsWebURLWithMaxCount 關(guān)鍵字的值不為0(更多關(guān)于在應(yīng)用擴(kuò)展中通過JavaScript訪問網(wǎng)頁的內(nèi)容請參閱Accessing a Webpage

你也可以使用 NSExtensionItem 定義的 UTI子 類型以便數(shù)據(jù)檢測器檢測文本信息,比如電話號碼或通訊地址缀旁。

NSExtensionActivationRule字典中的鍵足以滿足大多數(shù)應(yīng)用的過濾需求记劈。如果你需要做更復(fù)雜的過濾,比如像 public.urlpublic.image 之間的區(qū)別并巍,那么你就得在文本中創(chuàng)建斷言語句抠蚣。如果你要創(chuàng)建一個斷言,那么就將NSExtensionActivationRule關(guān)鍵字的值設(shè)置為你指定的斷言字符串履澳。(在運(yùn)行時嘶窄,系統(tǒng)會自動將該字符串編譯為 NSPredicate 對象

比如怀跛,一個應(yīng)用擴(kuò)展的附件屬性可以指定為PDF文件,可以這樣寫:

{extensionItems = ({
    attachments = ({
        registeredTypeIdentifiers = (
            "com.adobe.pdf",
            "public.file-url"
        );
    });
})}

為了指定你的應(yīng)用擴(kuò)展可以處理PDF文件柄冲,你可以像這樣創(chuàng)建斷言字符串:

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

此語句遍歷一個NSExtensionItem對象數(shù)組吻谋,其次是遍歷attachments每個擴(kuò)展項(xiàng)中的數(shù)組。對于每個附件现横,謂詞評估附件中每個表示的統(tǒng)一類型標(biāo)識符(UTI)漓拾。當(dāng)附件表示UTI符合兩個不同的指定UTI中的任何一個(您在每個UTI-CONFORMS-TO操作員的右側(cè)看到)時,收集該UTI以進(jìn)行最終比較測試戒祠。TRUE如果應(yīng)用程序擴(kuò)展名僅提供了一個支持UTI的擴(kuò)展項(xiàng)附件骇两,則返回最后一行。

開發(fā)過程中姜盈,在你創(chuàng)建斷言語句之前你可以使用TRUEPREDICATE常量(結(jié)果為true)測試你的代碼路徑低千。更多斷言語句的語法知識請參閱Predicate Format String Syntax。

重要提示:在將你的載體應(yīng)用上傳App Store之前馏颂,要確保所有的 TRUEPREDICATE 常量已經(jīng)替換為指定的斷言語句或 NSExtensionActivationRule 關(guān)鍵字示血,不然載體應(yīng)用會被App Store拒絕。

配置載體應(yīng)用以適用于老版本的iOS系統(tǒng)

如果你在主體應(yīng)用中使用了內(nèi)嵌框架救拉,那么它就可以在iOS8.0之后的版本中使用难审,即便內(nèi)嵌框架不支持老版本的系統(tǒng)也沒關(guān)系。

使主體應(yīng)用能做到上述這一點(diǎn)的是 dlopen 命令亿絮,它可以使你使用條件鏈接和加載框架包的機(jī)制告喊。你可以使用這個命令來代替編譯時鏈接,你可以在 Xcode 的 General 選項(xiàng)或 Build Phases 選項(xiàng)中對該命令進(jìn)行編輯派昧。其原理就是只有當(dāng)主體應(yīng)用在 iOS8.0 或更高的版本中運(yùn)行時葱绒,才會鏈接使用內(nèi)嵌框架。

您必須在有條件地 framework bundle的代碼語句中使用Objective-C而不是Swift斗锭。您的應(yīng)用程序的其余部分可以用任何一種語言編寫,內(nèi)嵌框架本身也可以用任何一種語言編寫失球。

調(diào)用之后dlopen岖是,使用以下類型的語句訪問內(nèi)嵌框架類:

MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init]; 

重要提示:如果你的主體應(yīng)用使用了內(nèi)嵌框架,那么就必須要支持arm64架構(gòu)实苞,否則會被App Store拒絕豺撑。

設(shè)置Xcode項(xiàng)目中應(yīng)用擴(kuò)展的條件鏈接

1.將每一個應(yīng)用擴(kuò)展的運(yùn)行系統(tǒng)版本設(shè)置為iOS8.0或更高,通常選中Xcode中的target黔牵,在General選項(xiàng)中設(shè)置Deployment info聪轿。
2.將你主體應(yīng)用的運(yùn)行系統(tǒng)版本設(shè)置為你想支持的最低iOS版本。
3.在你的主體應(yīng)用中猾浦,通過 systemVersion 方法陆错,在運(yùn)行時檢查判斷iOS的版本灯抛,并判斷是否執(zhí)行dlopen命令。只有你的載體應(yīng)用在iOS8.0或更高的版本中運(yùn)行時才會指定dlopen命令音瓷。進(jìn)行此調(diào)用時对嚼,請務(wù)必使用Objective-C,而不是Swift绳慎。

特定的iOS API通過dlopen命令使用內(nèi)嵌框架纵竖。你必須選擇性的使用這些API,就像使用 dlopen 命令時那樣杏愤。這些API都是 CFBundleRef 的封裝類型:

CFBundleGetFunctionPointerForName

CFBundleGetFunctionPointersforNames

還有來自NSBundle類的方法:

loadloadAndReturnError:
classNamed:

因?yàn)槟阋话銜⑤d體應(yīng)用的運(yùn)行系統(tǒng)版本配置為較低的版本靡砌,所以這些API通常都是在運(yùn)行時檢查,只有確保載體應(yīng)用在iOS8.0或更高版本中運(yùn)行時才會使用這些API珊楼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末通殃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亥曹,更是在濱河造成了極大的恐慌邓了,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件媳瞪,死亡現(xiàn)場離奇詭異骗炉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛇受,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門句葵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兢仰,你說我怎么就攤上這事乍丈。” “怎么了把将?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵轻专,是天一觀的道長。 經(jīng)常有香客問我察蹲,道長请垛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任洽议,我火速辦了婚禮宗收,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亚兄。我一直安慰自己混稽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匈勋,像睡著了一般礼旅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颓影,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天各淀,我揣著相機(jī)與錄音,去河邊找鬼诡挂。 笑死碎浇,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的璃俗。 我是一名探鬼主播奴璃,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼城豁!你這毒婦竟也來了苟穆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤唱星,失蹤者是張志新(化名)和其女友劉穎雳旅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體间聊,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡攒盈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哎榴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片型豁。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尚蝌,靈堂內(nèi)的尸體忽然破棺而出迎变,到底是詐尸還是另有隱情,我是刑警寧澤飘言,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布衣形,位于F島的核電站,受9級特大地震影響姿鸿,放射性物質(zhì)發(fā)生泄漏谆吴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一般妙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧相速,春花似錦碟渺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芜繁。三九已至,卻和暖如春绒极,著一層夾襖步出監(jiān)牢的瞬間骏令,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工垄提, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留榔袋,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓铡俐,卻偏偏與公主長得像凰兑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子审丘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1吏够、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,988評論 3 119
  • 當(dāng)暗黑的天邊泛起曙光, 迎來了那一絲光芒滩报, 當(dāng)金色的光芒現(xiàn)起東方锅知, 灑向那圓滑的肌膚, 當(dāng)清晨的鐘聲緩緩響起脓钾, 鬧...
    花開花落情意殤閱讀 364評論 4 10
  • 今天6點(diǎn)鐘陳睿就起床去拿貨了售睹。8點(diǎn)半回來了,沒拿到貨惭笑。 他繼續(xù)睡侣姆,我起來洗洗臉,去黑頭沉噩,并沒有什么黑頭吸出來捺宗,我的...
    清和簡閱讀 175評論 0 0