參考:iOS使用Workspace來(lái)管理多項(xiàng)目歇万,個(gè)人覺(jué)得這篇文章講解的不錯(cuò)嘲更。
前言
Workspace凝颇,工作空間潘拱,可以用來(lái)管理多個(gè)Xcode Project,像Cocoapods一樣拧略,它的常見(jiàn)用法是編譯靜態(tài)庫(kù)芦岂,然后給主工程使用,但跟普通的制作.a
和.framework
不同的是辑鲤,它不需要先打開(kāi)靜態(tài)庫(kù)工程編譯盔腔,然后將生成的.a
或.framework
拷貝到主工程,最后再編譯主工程月褥,這樣會(huì)造成很強(qiáng)的割裂感弛随。Workspace只需要編譯主工程,即可將依賴的工程一同編譯宁赤,體驗(yàn)會(huì)更好一些舀透。
制作Workspace
1.新建一個(gè)Workspace項(xiàng)目
菜單File -> New -> Workspace,新建一個(gè)Workspace項(xiàng)目决左,如下圖所示愕够,之后會(huì)生成一個(gè).xcworkspace
文件走贪,雙擊打開(kāi)該文件,會(huì)發(fā)現(xiàn)什么都沒(méi)有惑芭,其實(shí)Workspace就類(lèi)似一個(gè)文件夾坠狡,將不同的Project放在一起編譯。
2.向Workspace添加Project
本Demo包含2個(gè)Project遂跟,一個(gè)靜態(tài)庫(kù)項(xiàng)目BookObtain
逃沿,另一個(gè)是主工程BookManager
,如圖幻锁,BookObtain
用來(lái)模擬從網(wǎng)絡(luò)下載書(shū)籍信息凯亮,BookManager
用來(lái)展示下載的書(shū)籍信息。
BookObtain
核心代碼如下:
// BookObtain.h
#import <Foundation/Foundation.h>
#import "Book.h"
@interface BookObtain : NSObject
+ (Book *)obtainBookWithURL:(NSString *)urlString;
@end
// BookObtain.m
@implementation BookObtain
+ (Book *)obtainBookWithURL:(NSString *)urlString {
NSDictionary *info = @{
@"name": @"算法導(dǎo)論",
@"price": @(125.0),
@"content": @"內(nèi)容太長(zhǎng)哄尔,xxx意思一下..."
};
Book *book = [Book bookWithInfo:info];
return book;
}
@end
// Book.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface Book : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) CGFloat price;
@property (nonatomic, copy) NSString *content;
+ (instancetype)bookWithInfo:(NSDictionary *)info;
@end
NS_ASSUME_NONNULL_END
// Book.m
#import "Book.h"
@implementation Book
- (instancetype)initWithInfo:(NSDictionary *)info {
if (self = [super init]) {
self.name = info[@"name"];
self.price = [info[@"price"] floatValue];
self.content = info[@"content"];
}
return self;
}
+ (instancetype)bookWithInfo:(NSDictionary *)info {
return [[self alloc] initWithInfo:info];
}
@end
完成BookObtain
代碼編寫(xiě)假消,需要在主工程引用,這時(shí)候你會(huì)發(fā)現(xiàn)#import "BookObtain.h"
報(bào)錯(cuò)岭接,找不到頭文件富拗。這就是靜態(tài)庫(kù)引用需要做的第一件事:指定頭文件路徑。
在主工程的 Build Settings -> Header Search Paths 添加一項(xiàng) $(SRCROOT)/../BookObtain
亿傅,并且設(shè)置為recursive媒峡。
現(xiàn)在引入頭文件不報(bào)錯(cuò)了,在主工程的ViewController.m
中添加如下代碼:
// 點(diǎn)擊按鈕回去書(shū)籍信息
- (IBAction)obtainBookInfo:(UIButton *)sender {
Book *book = [BookObtain obtainBookWithURL:@"xxx"];
self.bookLbl.text = [NSString stringWithFormat:@"name:%@\nprice:%.2lf\ncontent:%@", book.name, book.price, book.content];
}
編譯葵擎,發(fā)現(xiàn)報(bào)錯(cuò):
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_BookObtain", referenced from:
objc-class-ref in ViewController.o
這涉及到引用靜態(tài)庫(kù)的第二個(gè)問(wèn)題:添加.a
文件
在主工程的 Build Phases -> Link Binary With Libraries 添加 libBookObtain.a
文件谅阿,如下圖:
至此,Workspace管理2個(gè)Project基本就完成了酬滤。
3.bundle攜帶資源文件
眾所周知签餐,.a
文件是不能攜帶資源文件的,那如果靜態(tài)庫(kù)有資源文件怎么辦呢盯串?使用bundle氯檐。
在BookObtain
工程的TARGETS
下添加一個(gè)新的target,類(lèi)型是macOS下的Bundle
体捏,操作如下圖:
注意:因?yàn)锽undle只在macOS下才有冠摄,所以創(chuàng)建完成之后,需要將該target的
Base SDK
從macOS
改為iOS
几缭。
然后將需要添加的資源文件拖到Bundle
中即可河泳。
因?yàn)橹鞴こ绦枰褂迷揃undle中的資源文件,所以需要保證該Bundle的target優(yōu)先編譯年栓,修改主工程的Build選項(xiàng)拆挥,讓該Bundle的target在主工程target之前進(jìn)行編譯。
最后某抓,需要將該bundle編譯的產(chǎn)物拷貝到主工程的main bundle下纸兔。
主工程的 Build Phases 左上角點(diǎn)擊 + 號(hào)惰瓜,添加一個(gè)New Run Script Phase
,在里面添加拷貝bundle的腳本命令汉矿,如下:
#!/bin/sh
cp -R ${BUILT_PRODUCTS_DIR}/BookObtainBundle.bundle ${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.app
然后就可以在主工程使用該bundle中的資源文件了崎坊。
NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"BookObtainBundle.bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
NSString *imgPath = [[bundle resourcePath] stringByAppendingPathComponent:@"1.jpeg"];
self.imgView.image = [UIImage imageWithContentsOfFile:imgPath];
總結(jié)
上面的Demo講解了Workspace的用法,主要就是用來(lái)管理多個(gè)Project负甸,這種方式可以消除普通靜態(tài)庫(kù)制作的割裂感流强,但是它也有弊端,就是代碼是暴露出來(lái)的呻待,比較適用于企業(yè)內(nèi)部不同項(xiàng)目間共享代碼。如果你不想讓別人看到你的代碼队腐,那你只能用傳統(tǒng)的制作靜態(tài)庫(kù)的方式了蚕捉。