LoginSignup
32
32

More than 5 years have passed since last update.

CocoaPodsを利用したPrivate Static Libraryの作り方(和訳&ちょっと意訳)

Last updated at Posted at 2014-07-23

引用サイト: http://blog.sigmapoint.pl/developing-static-library-for-ios-with-cocoapods/

著者:Kamil Burczyk

  • project生成でCocoa Touch Static Libraryを選択します。project名はNetworkLibとします。

    image01.png

  • pod init でPodfileを作成します。

  • Podfileを以下のように編集します。

platform :ios, "7.0"  
target "NetworkLib" do  
pod 'AFNetworking'  
end  
target "NetworkLibTests" do  
end  
  • pod install すると以下の様にPodsフォルダが作成されます。

image02.png

  • アプリケーション内で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に以下のエラーが表示されるはずです。

image03.png

これは標準的な挙動であり、CocoaPodsライブラリがtestフェーズにリンクされていないデフォルトの設定であるためです。直していきましょう。

青いprojectアイコンをクリックして、ConfigurationsセクションのBased Configuration File欄でPods-NetworkLibを選択してください。

image04.png

これで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が中に入っているはずです。

image05.png

  • 以下の様にして作成したライブラリの関数を使ってみましょう。
#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

問題が無ければ動きます。

32
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
32