iOS組件化開發之私有庫創建(中)

前言

上一節我們通過把代碼簡單的拆分上傳至github,通過cocoapods的遠程私有庫,把拆分的代碼當作第三方庫供我們使用,但是這種方式存在很多問題,實際項目使用這種簡單粗暴的拆分也不可取,所以今天講上一篇博客提到的第二種私有庫創建方式,后面統一把私有庫稱作組件。

最后大概結構
image.png

本文要講的是改變組件創建的方式,解決:

  • 組件使用.framework或者.a這兩種靜態庫的方式創建
  • 組件單獨依賴第三方,即有自己的podfile文件配置使用
  • 組件有自己單獨的資源文件,在自己組件中使用資源文件
  • 組件工程調試及配置使用

吐槽部分可跳過

關于創建靜態庫的方式:

  1. 使用pod命令也就是pod lib命令創建
  2. 自己通過xcode手動創建

兩種方式也無所謂好壞,都能夠達到創建組件的目的。我想要說的是手動創建好處:

  1. 手動創建可以知道創建過程都做了什么,pod命令如果不去深究不能很明白原理。
  2. pod命令創建的組件只能放在Development Pods文件夾目錄下
    ,對于手動創建使用target依賴的方式的方式來說顯得不是很友好。
  3. pod命令創建的組件要添加資源文件時配置麻煩,手動創建簡單。

當然手動創建也有缺點:

  1. pod命令創建方便快捷,手動創建相對步驟多
  2. 創建和編譯過程需要踩坑。

總結:

  1. 如果是單純抽取一些小東西用命令就可以沒必要折騰
  2. 如果項目要大規模使用組件化建議手動創建方式

正文

上面說過創建組件靜態庫有兩種,一種是.framwework另外一種是.a,兩種方式創建大同小異。這里先以創建.a靜態庫的方式創建,相關節點配置不同點我會說明。

創建

打開xcode創建進入選擇創建菜單


屏幕快照 2018-06-29 11.47.46.png

上圖中Cocoa Touch Framework就是創建.framework靜態庫的方式,我們先創建.a形式的靜態庫 選中Cocoa Touch Static Library點擊 next,填寫你組件靜態庫的名稱完成。

創建好之后像這樣:


image.png

初始文件:

  1. 幫我們創建和靜態庫名稱一樣的文件夾和類(頭文件)。
  2. 把創建的頭文件加入到Copy Files 里面,這里要關心的一點是,如果你修改了頭文件這里也要添加相應你要暴露的頭文件,這里的頭文件可以是多個也就是你想暴露多少個就添加多少個。

添加podfile:

使用pod init 命令在根目錄添加 podfile,這里簡單添加Masonry


platform :ios, '8.0'

target 'StaticKit' do

    pod 'Masonry'

end

進行pod install命令之后我們可以看到pod給我們黃色的警告

image.png

主要是前面的錯誤:

[!] The Podfile contains framework or static library targets (StaticKit), for which the Podfile does not contain host targets (targets which embed the framework).
If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).

這大概的意思是說當前的target為靜態庫,而且pod依賴的是當前這個靜態庫不是依賴host targets,host targets我的理解是可執行的target,當時我沒注意這個警告以為是普通的警告,之后添加到殼工程的時候會提示該靜態庫的pod找不到

當然最后如果我們認真看提示的警告已經告訴了我們解決的辦法了,最后一行的括號內(e.g. a test target)。這就是讓我們創建一個測試的targetpod依賴它就可以讓這個警告消失。這個很多網上文章都是一筆帶過沒說清楚的,不然就是不提靜態庫添加第三方依賴的問題,當然我的解釋也不一定對。

靜態庫需要添加一個測試target讓第三方依賴

添加測試target

點擊+按鈕進入選擇target菜單

image.png

選中iOS Unit Testing Bundle 取名為 StaticKitTests

image.png

創建好之后是這樣

image.png

修改podfile重新更新


platform :ios, '8.0'

project 'StaticKit'
#修改為測試的target
target 'StaticKitTests' do

    pod 'Masonry'

end

更新后的 pod信息,發現已經正常了

image.png

到這里如果你把Masonry 導入項目的類的時候會發現提示無法找到頭文件,這時候我們要設置Heaser Search Paths 設置路徑 添加 "$(SRCROOT)/Pods/Headers/Public"

image.png

添加資源文件:

添加資源文件我一般可以簡單創建一個bundle放到工程目錄下,使用時添加工程下就行了。這種方式很簡單也是可以用的,但是這樣的方式不容易管理我們的資源文件。在這里我推薦把資源文件也當作一個target添加到靜態庫組件中,過程和上面創建測試target差不多只是需要一些配置。

點擊+好到創建target界面,tab頁選中macOS下面的 Bundle,下一步 我取名為StaticKit_res按自己需要可以改名字

image.png

創建好之后是這樣的

image.png

創建的時候你可以看到我們創建的是macOSbundle,至于為什么要用mac不用iOS很簡單因為iOS沒有這個選項,所以為了適配iOS 我們需要做下面兩個配置

  1. 配置Base SDKiOS 配置路徑看下圖
image.png
  1. 一般我們圖片有@2x @3x這樣放在bundle會導致讀取圖片失敗,所以我們要改下配置,把COMBINE_HIDPI_IMAGES設置為NO
image.png

讀取資源文件:

我們的組件的資源文件基礎配置已經好了,接下來要添加一個工具類來讀取資源了,在這里我們以讀取圖片資源為例,其他的資源大同小異。

  1. 我們添加幾張測試圖片放到staticKit_res文件夾下,記得target的選擇
image.png
  1. 創建我們的工具類名稱為StaticKitHelper代碼如下
@interface StaticKitHelper : NSObject


+ (NSBundle *)resBundle:(Class)classtype;
    
+ (UIImage*)imageName:(NSString*)name;
    
@end

#import "StaticKitHelper.h"

@implementation StaticKitHelper
    
    
+ (NSBundle *)resBundle:(Class)classtype {
    static NSBundle *framworkBundle = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        framworkBundle = [NSBundle bundleForClass:classtype];
        if (framworkBundle) {
            NSString *resourceBundlePath = [framworkBundle pathForResource:@"StaticKit_res" ofType:@"bundle"];
            if (resourceBundlePath && [[NSFileManager defaultManager] fileExistsAtPath:resourceBundlePath]) {
                framworkBundle = [NSBundle bundleWithPath:resourceBundlePath];
            }
        }
    });
    return framworkBundle;
}
    
+ (UIImage*)imageName:(NSString*)name {
    
    if (name.length == 0) {
        return nil;
    }
    NSBundle *bundle = [StaticKitHelper resBundle:[self class]];
    NSString *path = [bundle pathForResource:name ofType:@"png"];
    
    return [UIImage imageWithContentsOfFile:path];
}
@end

//調用
UIImage *image = [StaticKitHelper imageName:@"PlayButtonOverlayLarge"];

添加測試代碼:

通過上面的設置我們的.a靜態庫組件基礎配置已經好了,接下來我們要添加測試代碼,我這里把默認的頭文件普通的類改成一個控制器類,設置背景為藍色,并添加了一張圖片:

#import "StaticKit.h"
#import "StaticKitHelper.h"
#import <Masonry/Masonry.h>


@implementation StaticKit

    
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"StaticKit控制器";
    
    
    UIImage *image = [StaticKitHelper imageName:@"PlayButtonOverlayLarge"];
    
    UIImageView *imageView = [UIImageView new];
    imageView.image = image;
    [self.view addSubview:imageView];
    [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view).offset(100);
        make.top.equalTo(self.view).offset(100);
        make.size.mas_equalTo(CGSizeMake(40, 40));
    }];
    
    self.view.backgroundColor = [UIColor blueColor];
}

    
@end

到這里StaticKit組件已經是一個合格的靜態庫組件了,它可以參與模塊的開發了,最后總結下大概的步驟:

  1. 打開xcode創建Cocoa Touch Static Library設置組件名字
  2. 添加測試target,創建podfile設置依賴的target為測試StaticKitTests
  3. 添加資源文件target StaticKit_res 設置兩個編譯參數,導入測試圖片
  4. 添加讀取資源工具類,添加測試代碼
  5. 編寫的代碼在自己的靜態庫組件內編譯通過

添加殼工程調試:

  • 準備工作

所謂的殼工程就是我平常創建可以直接運行的工程,你可以隨便創建一個帶導航欄的控制器,用于push到我們的靜態庫組件供調試,這個步驟很簡單就不廢話了默認你已經創建好了殼工程。

  • 添加到殼工程
  1. 打開殼工程將StaticKit.xcodeproj拖到殼工程下
image.png
  1. 點擊殼工程選中Build PhasesTarget Dependencies下點+號 添加StaticKitStaticKit_res
image.png
  1. 在同一個地方的Link Binary With Libraries添加StaticKit
image.png
  1. 在靜態庫中的Products文件夾下的StaticKit_res拖到Copy Bundle Resources
image.png
  1. 編譯下如果顯示成功就算大功告成了,如果有報錯你可以回頭看上面那個步驟做錯了或者漏了。

這里解釋下

第一步沒什么好解釋的。
第二步是我們把兩個target當作子target依賴殼工程。
第三步表示代碼執行我們鏈接的是StacKit這個target而不包含StaticKit_res。
第四步是把我們靜態庫的資源文件添加到mainBundle里面這樣我們才可以通過代碼找得到它。

添加殼工程測試代碼:

//第三方方式訪問,這個頭文件在我們創建的時候有說要設置才能訪問
#import <StaticKit/StaticKit.h>

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"點擊跳轉到庫";
}[圖片上傳中...(show.gif-f0b9fe-1530268184126-0)]



- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    StaticKit *sk = [[StaticKit alloc]init];
    [self.navigationController pushViewController:sk animated:YES];
}

@end

運行截圖

show.gif

到這里自己手動創建.a靜態庫的全過程就完了,接下來會說.a靜態庫和.framework靜態庫配置,framework的創建和.a基本流程是一致的,某些配置有細微差別。

.framework靜態庫的差異

  1. framework的靜態庫創建的時候默認都是動態的,但是上架是不允許動態的所以我要在Build Settings里面的Mach-O Type設置為Static Library
image.png

2.framework設置的頭文件不一樣,framework創建的時候頭文件都會默認顯示在Project下我們需要把它拖到Public

image.png

3.最后一個不同點就是加人殼工程是frameworkKit.framework不需要加入到Target Dependencies

image.png

本文到這里就交代完手動創建靜態庫到調試的全部內容了,如果有寫錯的地方或者有什么問題你可以在本文下方評論,也希望大家都交流學習。下篇帶大家編譯靜態庫到遠程私有庫,敬請期待!

參考資料

https://www.raywenderlich.com/65964/create-a-framework-for-ios
https://github.com/jverkoey/iOS-Framework

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容