最近在研究將iOS工程打包成靜態庫并從中創建ViewController的方法。其中遇到了很多坑,經過兩天的折騰,終于理清了其中的邏輯。鑒于這兩天的折騰并沒有搜索到很實用的教程,因此本文就一步一步向各位演示如何實現將工程打包為靜態庫,并從中創建storyboard。
1.打包靜態庫并拖入項目
首先將打包了storyboard和代碼文件的靜態庫TempFramework.framework拖入項目,并從framework文件中讀取storyboard文件(我這里的storyboard名為BasicMain)。
創建代碼如下
NSString *path = [[NSBundle mainBundle] pathForResource:@"TempFramework" ofType:@"framework"];
NSLog(@"path = %@", path);
NSBundle *myBundle = [NSBundle bundleWithPath:path];
NSLog(@"myBunlde = %@", myBundle);
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"BasicMain" bundle:myBundle];
NSLog(@"%@", storyboard);
此時運行會報錯
打印結果與錯誤原因如下:
01-測試用靜態庫創建ViewController[3103:145256] path = (null)
01-測試用靜態庫創建ViewController[3103:145256] myBunlde = (null)
01-測試用靜態庫創建ViewController[3103:145256] *** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'Could not find a storyboard named 'BasicMain' in bundle NSBundle
</Users/yzzy/Library/Developer/CoreSimulator/Devices/
0F87417C-9FF4-4F09-B1F7-
10C4E7BB4301/data/Containers/Bundle/Application/E9ADFEBA-
86F0-46E1-B386-61202991AF7A/01-測試用靜態庫創建ViewController.app> (loaded)'
從上述打印結果可以看出,這是因為系統沒有找到framework文件路徑。這里需要補充iOS中關于bundle的介紹:
Bundle簡單地講,就是一個內部結構按照標準規則組織的特殊目錄
iOS的應用都是通過bundle進行封裝的,對應的bundle類型是Application類型,平時我們通過XCode編譯出來的Target(即我們開發的應用),其實就是一個Application類型bundle,即一個文件夾!但是Finder會把這個bundle當做一個文件顯示給我們,其實是因為這個bundle自身也是一個package,而Mac系統會把所有的package當做一個文件來對待,顯示給用戶,從而防止用戶誤操作導致程序文件損壞或丟失。至于bundle和package有什么區別,就不在這里展開說明了,本文后面所說的bundle都會被Mac系統視為package。
bundle的種類:
1. Application
2. Frameworks
3. Plug-Ins
本質上bundle文件就是一個文件夾,因此framework也是一個文件夾,iOS開發中,如果需要從bundle文件中讀取數據,需要在builder phase中將bundle文件加入Copy Bundle Resources。在這里沒有讀取到framework的原因正是因為我們雖然把framework文件拖入了項目,但是沒有將它加入到Copy Bundle Resources中。
此時再運行項目,則可成功讀取framework路徑,并創建storyboard
2.storyboard創建ViewController并跳轉
讀取到storyboard路徑后,接下來就要根據storyboard創建ViewController并跳轉到創建的ViewController。代碼如下:
NSString *path = [[NSBundle mainBundle] pathForResource:@"TempFramework" ofType:@"framework"];
NSLog(@"path = %@", path);
NSBundle *myBundle = [NSBundle bundleWithPath:path];
NSLog(@"myBunlde = %@", myBundle);
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"BasicMain" bundle:myBundle];
NSLog(@"%@", storyboard);
StoryboardOneViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"StoryboardOneViewController"];
[self presentViewController:vc animated:YES completion:nil];
此時運行進行跳轉時會報錯
錯誤原因:
01-測試用靜態庫創建ViewController[3560:181383] path =
/Users/yzzy/Library/Developer/CoreSimulator/Devices/0F87417C-
9FF4-4F09-B1F7-
10C4E7BB4301/data/Containers/Bundle/Application/B67631C8-
087A-4BE9-8AC0-E08178A83199/01-測試用靜態庫創建
ViewController.app/TempFramework.framework
01-測試用靜態庫創建
ViewController[3560:181383] myBunlde = NSBundle
</Users/yzzy/Library/Developer/CoreSimulator/Devices/0F87417C-
9FF4-4F09-B1F7-
10C4E7BB4301/data/Containers/Bundle/Application/B67631C8-
087A-4BE9-8AC0-E08178A83199/01-測試用靜態庫創建
ViewController.app/TempFramework.framework> (not yet loaded)
01-測試用靜態庫創建
ViewController[3560:181383] <UIStoryboard: 0x608000265680>
01-測試用靜態庫創建
ViewController[3560:181383] Unknown class
StoryboardOneViewController in Interface Builder file.
01-測試用靜態庫創建
ViewController[3560:181383] *** Terminating app due to uncaught
exception 'NSUnknownKeyException', reason: '[<UIViewController
0x7fa4bbf0d4b0> setValue:forUndefinedKey:]: this class is not key
value coding-compliant for the key testBtn.'
解決這里的錯誤,需要在build setting的other linker flags屬性中,添加參數-ObjC(注意大小寫)。
這樣就完成了從framework中加載storyboard并創建ViewController的全部工作。運行項目,跳轉成功!