引用サイト: http://blog.sigmapoint.pl/developing-static-library-for-ios-with-cocoapods/
著者:Kamil Burczyk
-
project生成でCocoa Touch Static Libraryを選択します。project名は
NetworkLib
とします。 -
pod init
でPodfileを作成します。 -
Podfileを以下のように編集します。
platform :ios, "7.0"
target "NetworkLib" do
pod 'AFNetworking'
end
target "NetworkLibTests" do
end
-
pod install
すると以下の様にPodsフォルダが作成されます。
- アプリケーション内でCocoapodsに依存したprojectを使用するには
podspec
ファイルを持つ必要があり、以下の様に作成します。podspecがよくわからないという方はこちらを参照してください。(英語)Cocoapods: Creating a Pod Spec
pod spec create NetworkLib
簡単に説明すると、作成したライブラリないしコンポーネントの対応プラットフォームやARC対応の有無、依存するフレームワークなどを記述したファイルです。
-
NetworkLib.podspec
を以下の様に編集
Pod::Spec.new do |s|
s.name = "NetworkLib"
s.version = "0.0.1"
s.summary = "A short description of NetworkLib."
s.description = <<-DESC
A longer description of NetworkLib in Markdown format.
DESC
s.homepage = "http://EXAMPLE/NetworkLib"
s.license = 'MIT (example)'
s.author = { "Kamil Burczyk" => "kamil.burczyk@sigmapoint.pl" }
s.platform = :ios, '7.0'
s.source_files = 'NetworkLib', 'NetworkLib/**/*.{h,m}'
s.public_header_files = 'NetworkLib/**/*.h'
s.resources = "NetworkLib/*.png"
s.framework = 'SystemConfiguration'
s.requires_arc = true
s.dependency 'AFNetworking'
end
すべてを上記の様に記述する必要はありませんが、s.source_files
,s.public_header_files
,s.resources
は自身のprojectパスにマッチする必要があり、s.framework
には依存するframeworkをかく必要があります。例えば、SystemConfiguration.framework
に依存するのであれば、上記のように記述します。そして最後にPodfileのdependenciesを
s.dependency 'AFNetworking'
のように記述します。s.source
は今回はプライベートライブラリであり、外部に公開しないので削除します。
- では何か書いてみましょう。
任意のユーザーのgithubリポジトリに関するすべての情報を取得する関数を書いてみましょう。使用するAPIはhttps://api.github.com/users/<username>/repos
です。
NetworkLib.h
:
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
@interface NetworkLib : NSObject
- (void)getGithubReposForUser:(NSString*)user withSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure;
@end
NetworkLib.m
:
#import "NetworkLib.h"
@implementation NetworkLib
- (void)getGithubReposForUser:(NSString*)user withSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:[NSString stringWithFormat:@"https://api.github.com/users/%@/repos", user] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
@end
テストコードを書いてみましょう。
#import <XCTest/XCTest.h>
#import "NetworkLib.h"
@interface NetworkLibTests : XCTestCase
@end
@implementation NetworkLibTests
- (void)testGetReposForBurczyk
{
NetworkLib *nl = [[NetworkLib alloc] init];
XCTAssertNotNil(nl, @"");
}
@end
ここでCmd+U
とコマンドを打つと、NetworkLib.h
に以下のエラーが表示されるはずです。
これは標準的な挙動であり、CocoaPodsライブラリがtestフェーズにリンクされていないデフォルトの設定であるためです。直していきましょう。
青いprojectアイコンをクリックして、Configurations
セクションのBased Configuration File
欄でPods-NetworkLib
を選択してください。
これでtestができるはずです。今回は非同期関数(asynchronous method)なので、結果が出るまで待つために、ちょっとした細工をします。そうしないと結果を得る前にtestが終了してしまいます。@Holtwick
さんのstackoverflowを利用しました。
包括的なテストコードは以下の様になります:
#import <XCTest/XCTest.h>
#import "NetworkLib.h"
@interface NetworkLibTests : XCTestCase
@end
@implementation NetworkLibTests
- (void)testGetReposForBurczyk
{
__block id JSON;
hxRunInMainLoop(^(BOOL *done) {
NetworkLib *nl = [[NetworkLib alloc] init];
[nl getGithubReposForUser:@"burczyk" withSuccess:^(id responseObject) {
NSLog(@"Response: %@", responseObject);
JSON = responseObject;
*done = YES;
} failure:^(NSError *error) {
*done = YES;
}];
});
XCTAssertNotNil(JSON, @"");
}
- (void)testGetRepoForNotExistingUser
{
__block id JSON;
hxRunInMainLoop(^(BOOL *done) {
NetworkLib *nl = [[NetworkLib alloc] init];
[nl getGithubReposForUser:@"burczyk1234567890" withSuccess:^(id responseObject) {
NSLog(@"Response: %@", responseObject);
JSON = responseObject;
*done = YES;
} failure:^(NSError *error) {
*done = YES;
}];
});
XCTAssertNil(JSON, @"");
}
// Wrapper to test async methods: http://stackoverflow.com/questions/2162213/how-to-unit-test-asynchronous-apis
static inline void hxRunInMainLoop(void(^block)(BOOL *done)) {
__block BOOL done = NO;
block(&done);
while (!done) {
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow:.1]];
}
}
@end
成功する場合と失敗する場合を記述してあります。
では実際のappで使ってみましょう。
- 新しいiOS appを作り、名前を
ReposBrowser
として、作成したライブラリと同じ階層に置きます。
MacBook Pro:Projects kamil$ ls
NetworkLib ReposBrowser
- 作ったproject(ReposBrowser)内で
pod init
を走らせ、Podfile
を作成し、編集します。
ローカルにあるライブラリ(NetworkLib)との依存関係を追加するために以下のようにコードを書き加えます。
pod 'NetworkLib', :path => '../NetworkLib'
全体では以下の様になります。
Podfile
:
# Uncomment this line to define a global platform for your project
# platform :ios, "7.0"
target "ReposBrowser" do
pod 'NetworkLib', :path => '../NetworkLib'
end
target "ReposBrowserTests" do
end
もしNetworkLib.podspec
が正しく記述されているようでしたら、pod install
で以下のような結果が得られるはずです。
MacBook Pro:ReposBrowser kamil$ pod install
Analyzing dependencies
Fetching podspec for `NetworkLib` from `../NetworkLib`
Downloading dependencies
Installing AFNetworking (2.1.0)
Installing NetworkLib (0.0.1)
Generating Pods project
Integrating client project
[!] From now on use `ReposBrowser.xcworkspace`.
MacBook Pro:ReposBrowser kamil$
そしてXcodeのPodsプロジェクトブラウザにはNetworkLib
を持つDevelopment Pods
が中に入っているはずです。
- 以下の様にして作成したライブラリの関数を使ってみましょう。
#import "ViewController.h"
#import "NetworkLib.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self testLib];
}
- (void)testLib
{
NetworkLib *nl = [[NetworkLib alloc] init];
[nl getGithubReposForUser:@"burczyk" withSuccess:^(id responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSError *error) {
NSLog(@"%@",error);
}];
}
@end
問題が無ければ動きます。