如何在Xcode 6 iOS 8中創(chuàng)建一個FrameWork(翻譯文章)

原文:https://insert.io/frameworkios8xcode6/ 來自Oded Regev

網(wǎng)上充滿了關于如何構建一個iOS Framework的教程趾娃。然而摔桦,當我們開始了著手開始做這件事情時候,仍然必須克服一些不小的挑戰(zhàn)手负,才能夠得到以我們想要的方式工作的SDK。

此外臣镣,在Xcode 6中谣膳,蘋果極大地改變開發(fā)人員創(chuàng)建和構建Frameworks的方式,所以你會發(fā)現(xiàn)在互聯(lián)網(wǎng)上很多的frameworks制作教程都是沒有及時更新何吝。

在這篇文章中溉委,我們會告訴你,如何一步一步在iOS8創(chuàng)建和構建一個Framwork爱榕,本教程中的Framework源代碼可以在Github獲取到瓣喊。

我們將針對性指出下面這些重要的挑戰(zhàn):

  • 如何混合Swift和Objective-C代碼結合在同一個SDK中?
  • 如何構建能被所有相關的架構(armv7黔酥,armv7s藻三,arm64,i386)使用的framework絮爷。如果你只需要這一個解決方案趴酣,只需要添加一個新的構建階段(Build Phase)到項目中,并使用“run script“, 腳本ios-build-framework-script.sh可以在這篇文章的底部找到坑夯。

在我們的例子中岖寞,我們將使用一個管理器(Manager)啟用\禁用framework,CustomView類將包含(驚喜吧)一個自定義的UIView柜蜈。在這個例子中仗谆,我們要告訴你如何把xib文件和PNG文件資源整合在Framework中。

讓我們開始第1步 #1

1)從頭開始創(chuàng)建一個項目

因為Xcode6中有一個內(nèi)置的選項來創(chuàng)建一個動態(tài)的Framework項目淑履。選擇這個選項隶垮,如果你需要從頭開始創(chuàng)建一個框架,項目的選擇:

“靜態(tài)庫(Static Library)”和“框架(Framework)”的區(qū)別是什么秘噪?

“靜態(tài)庫”主要是將代碼編譯成.a文件的樣式狸吞,例如InsertLib.a≈讣澹可以通過導出的靜態(tài)庫與他人共享蹋偏,靜態(tài)庫中包含一些公共類和方法,客戶端獲取到靜態(tài)庫后可以使用這些公共類和方法至壤。

“Cocoa Touch Framework”實質(zhì)上是一個包威始,其中包含一個“動態(tài)庫(dynamic library)”,若干.h文件和資源文件。 “動態(tài)庫”的概念(換個詞“動態(tài)鏈接(dynamic linking)”) 就是有共享代碼的一個副本在單個設備中(CoreLocation.Framework就是一個例子)由所有鏈接到它的應用程序共享像街。這種動態(tài)鏈接的方式將提高系統(tǒng)的性能黎棠,通過最小化framework的內(nèi)存使用晋渺。

2)添加Manager類文件,下面是代碼:

InsertManager.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface InsertManager : NSObject

+(instancetype) sharedManager;

-(void) startManager;
-(void) stopManager;

-(void) showMessageInViewController:(UIViewController *)viewController;

-(BOOL) isManagerRunning;

@end

InsertManager.m

#import "InsertManager.h"
#import "CustomView.h"

@interface InsertManager()

@property (nonatomic) BOOL isEnabled;

@end

@implementation InsertManager

+ (instancetype) sharedManager {
   static InsertManager *sharedManager = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
      sharedManager = [[[self class] alloc] init];
   });
   return sharedManager;
}

- (void) startManager {
   NSLog(@"Manager is running");
   _isEnabled = YES;
}

- (void) stopManager {
   NSLog(@"Manager stopped..");
   _isEnabled = NO;
}

-(BOOL) isManagerRunning {
   return _isEnabled;
}

-(void) showMessageInViewController:(UIViewController *)viewController {
   if (_isEnabled) {
      NSBundle* frameworkBundle = [NSBundle bundleForClass:[self class]];
      CustomView *csView = [[frameworkBundle loadNibNamed:@"CustomView" owner:self options:nil] firstObject];
      csView.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
      [viewController.view addSubview:csView];
   }
}

@end

3)添加CustomView代碼:

CustomView.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface CustomView : UIView

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *closeButton;

@end

CustomView.m

#import "CustomView.h"

@implementation CustomView

- (IBAction)closeButtonClicked:(id)sender {
    [self removeFromSuperview];
}

@end

CustomView.xib - 下載從Github上脓斩,看看它是如何配置的木西。


Newsroom.png - 我們用這個文件作為背景圖片來演示,如何在一個框架中使PNG一類的資源文件并且傳給一個應用程序随静。

4)當你在Xcode中創(chuàng)建一個新的“Cocoa Touch Framework” 項目户魏,默認的.h文件將被自動命名生成的“項目名.h” 。請確保您的所有公開的.h文件添加到該文件中挪挤,公開.h文件中包含公開方法叼丑,客戶端可以通過framework調(diào)用這些公開方法,在我們的例子中添加以下代碼:

#import <UIKit/UIKit.h>

//扛门!InsertSampleFramework項目的版本號鸠信。

FOUNDATION_EXPORT double InsertSampleFrameworkVersionNumber;

//!InsertSampleFramework項目版本字符串论寨。

FOUNDATION_EXPORT const unsigned char InsertSampleFrameworkVersionString [];

//在這頭星立,你應該導入使用類似語句的框架的所有公共頭

#import <InsertSampleFramework/InsertManager.h>

5)在Xcode中單擊Target,并轉(zhuǎn)到“Build Phase”部分葬凳,在“Headers”中添加需要公開的.h文件到“Public”中

Build Phase:

6)現(xiàn)在只是建立了Framework绰垂,還沒有準備好調(diào)用framework的項目。我們只能夠使用該framework在一個項目應用中火焰。我們將在名為“Tabster”蘋果范例項目使用這個framework劲装。該項目的完整源代碼可以從iOS Developer Library 下載,搜索“Tabster”昌简,點擊結果占业。在Tabster頁面,查找按鈕“Download Sample Code”纯赎,下載代碼谦疾,并在Xcode打開項目。

來看看如何能夠讓我們的Framework在這個項目中工作起來...

在項目中集成framework

1)打開Tabster項目并運行應用程序犬金,看到它如我們期望一樣運行起來念恍。

2)復制“InsertSampleFramework”項目的根文件夾到Tabster的根文件夾

3)現(xiàn)在拖動Framework項目到Tabster項目中作為一個依賴(請注意,您必須先關閉Framework項目的Xcode的窗口晚顷,因為xcodeproj只可以在一個Xcode窗口中打開)峰伙。

4)加入該Framework作為依賴在Build Phases中

5)加入該框架為“Link Binary with Libraries”。如果框架有Swift代碼音同,你還需要添加框架中的““General”標簽下的“Embedded Binaries”

6)點擊Run词爬,看看它是是否能工作秃嗜,這個操作是一個完整性檢查(注意权均,我們還沒有用代碼集成framework)顿膨。

7)現(xiàn)在讓我們在Tabster項目中使用我們的神奇的Framework。Tabster這是一個相當簡單的應用程序:打開Storyboard 叽赊,并添加一個label(Insert Framework Enable\Disable)恋沃,UISegmentControl和一個UIButton到ThreeViewController

8)在Tabster的ThreeViewController.m中添加:

#import<InsertSampleFramework/InsertManager.h>

9)添加下面的IBActions到ThreeViewController.m:

#pragma mark - IBAction

- (IBAction)segmentValueChanged:(id)sender {
    UISegmentedControl *sc = (UISegmentedControl *)sender;
    NSInteger selectedSegment = sc.selectedSegmentIndex;
    if (selectedSegment == 1) {
        [[InsertManager sharedManager] startManager];
    }
    else if (selectedSegment == 0) {
        [[InsertManager sharedManager] stopManager];
    }
}

- (IBAction)showCustomView:(id)sender {
    [[InsertManager sharedManager] showMessageInViewController:self];
}

10)運行應用程序,點擊標簽“Three”必指,點擊 On\Off segment control囊咏。點擊確認按鈕“Show Custom View”將顯示view,確保manager運行時才能使用塔橡。

分發(fā)我們的framework使其能夠融合到其他外部應用程序中

大多數(shù)公司和個人開發(fā)為iOS開發(fā)框架(framework)梅割,最終希望將自己的框架能夠分發(fā)給別人使用。你必須要做的最重要的一步就是葛家,建立對所有可能的架構(armv7户辞,armv7s,arm64癞谒,X86等)都支持的框架底燎。一為架構的每個家庭(iPhone模擬器,舊設備(ARMv7的弹砚,armv7s)双仍,新設備(arm64) - 我們?yōu)榱俗龅竭@一點,通過增加一個“Build Phase”運行一個腳本桌吃,腳本將build framework3次朱沃。

點擊框架目標,并添加一個“New Run Script Phase”:

這一行你應該復制和粘貼到build phase:

/${PROJECT_DIR}/OTRGuideManager/ios-build-framework-script.sh

一些開發(fā)人員更喜歡直接在此框中寫腳本茅诱,我更傾向于讓腳本在一個單獨的sh文件为流,這樣我可以在Git的跟蹤它,當需要在未來让簿,他們跟蹤更改敬察。

具體的腳本是在ios-build-framework-script.sh:

set -e
set +u
#避免遞歸調(diào)用這個腳本。
if [[ $SF_MASTER_SCRIPT_RUNNING ]]
then
exit 0
fi
set -u
export SF_MASTER_SCRIPT_RUNNING=1

#常量
SF_TARGET_NAME=${PROJECT_NAME}
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

#構建Target
if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]
then
SF_SDK_PLATFORM=${BASH_REMATCH[1]}
else
echo "Could not find platform name from SDK_NAME: $SDK_NAME"
exit 1
fi

if [[ "$SF_SDK_PLATFORM" = "iphoneos" ]]
then
echo "Please choose iPhone simulator as the build target."
exit 1
fi

IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

#生成其他(非虛擬機)平臺
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" ARCHS='arm64' VALID_ARCHS='arm64' $ACTION

xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"  CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/armv7" SYMROOT="${SYMROOT}" ARCHS='armv7 armv7s' VALID_ARCHS='armv7 armv7s' $ACTION

#復制framework結構的universal folder(先清空)
rm -rf "${UNIVERSAL_OUTPUTFOLDER}"
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"

#把這些架構(architectures)攪碎融合到一起
lipo -create  "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/arm64/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/armv7/${PROJECT_NAME}.framework/${PROJECT_NAME}" -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

1)請確保選擇是iPhone模擬器尔当,當你想建立的發(fā)布版本的framework - 腳本會檢測莲祸,并自動建立的其他平臺。

2)運行“ Build”后椭迎,你需要選擇Distribution-universal目錄下的Framework锐帜。

3)整合framework到Xcode項目中,使用framework和你已經(jīng)配置好的設置畜号。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缴阎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子简软,更是在濱河造成了極大的恐慌蛮拔,老刑警劉巖述暂,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異建炫,居然都是意外死亡畦韭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門肛跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艺配,“玉大人,你說我怎么就攤上這事衍慎∽Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵稳捆,是天一觀的道長酝掩。 經(jīng)常有香客問我,道長眷柔,這世上最難降的妖魔是什么期虾? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮驯嘱,結果婚禮上镶苞,老公的妹妹穿的比我還像新娘。我一直安慰自己鞠评,他們只是感情好茂蚓,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剃幌,像睡著了一般聋涨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上负乡,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天牍白,我揣著相機與錄音,去河邊找鬼抖棘。 笑死茂腥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的切省。 我是一名探鬼主播最岗,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼朝捆!你這毒婦竟也來了般渡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驯用,沒想到半個月后脸秽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡晨汹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贷盲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淘这。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巩剖,靈堂內(nèi)的尸體忽然破棺而出铝穷,到底是詐尸還是另有隱情,我是刑警寧澤佳魔,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布曙聂,位于F島的核電站,受9級特大地震影響鞠鲜,放射性物質(zhì)發(fā)生泄漏宁脊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一贤姆、第九天 我趴在偏房一處隱蔽的房頂上張望榆苞。 院中可真熱鬧,春花似錦霞捡、人聲如沸坐漏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赊琳。三九已至,卻和暖如春砰碴,著一層夾襖步出監(jiān)牢的瞬間躏筏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工呈枉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寸士,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓碴卧,卻偏偏與公主長得像弱卡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子住册,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

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