Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カテゴリのメソッドがリンクされない

タグ: Objective-C iPhone
// Foo.h
#import <Foundation/Foundation.h>

@interface Foo : NSObject
- (void)methodInClass;
@end
// Foo.m
#import "Foo.h"

@implementation Foo
- (void)methodInClass
{
    NSLog(@"methodInClass");
}
@end
// Foo+Foo.h
#import "Foo.h"

@interface Foo (Foo)
- (void)methodInCategoryFoo;
@end
// Foo+Foo.m
#import "Foo+Foo.h"

@implementation Foo (Foo)
- (void)methodInCategoryFoo;
{
    NSLog(@"methodInCategoryFoo");
}
@end

以上4ファイルからiPhone向けの静的ライブラリを作成。

作成したライブラリをアプリケーションに-ObjCフラグ付きでリンクし、main.mで

#import <Foo.h>
#import <Foo+Foo.h>

@interface Foo (Mine)
- (void)methodInMyCategory;
@end

@implementation Foo (Mine)
- (void)methodInMyCategory
{
    NSLog(@"methodInMyCategory");
}
@end

int main(int argc, char *argv[]) {
    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    Foo * foo = [[[Foo alloc] init] autorelease];
    [foo methodInClass];
    [foo methodInMyCategory];
    [foo methodInCategoryFoo];

このようにして使ってみると、実機で実行した場合に限り、なぜかFooカテゴリのメソッドだけ呼び出すことができない(iPhone SDK 3.0)。

methodInClass
methodInMyCategory
*** -[Foo methodInCategoryFoo]: unrecognized selector sent to instance 0x113fe0

実機用の実行ファイルをnmしてみると、たしかにFooカテゴリのメソッドは見当たらない。

000021a4 t -[Foo methodInClass]
000020c4 t -[Foo(Mine) methodInMyCategory]

この現象は、Foo+Foo.mの中身(Fooカテゴリの実装)をFoo.mに移すことで解消される。

methodInClass
methodInMyCategory
methodInCategoryFoo
000021b8 t -[Foo methodInClass]
000021a4 t -[Foo(Foo) methodInCategoryFoo]
000020c4 t -[Foo(Mine) methodInMyCategory]

以上のことから考えるに、どうやらiPhone実機向けの静的ライブラリリンクでは、クラスの実装とは異なる中間ファイルで実装されたカテゴリのメソッドをリンクすることができないようだ。

この現象を回避するには、「クラスとカテゴリの実装を同じファイルにまとめる」ほかに、「他のリンカフラグ」に「-all_load」を追加するという方法もある。
これはこれで、逆に余計なものまでリンクするような気もするが……

スポンサーサイト

コメント

[C30]

すげー参考になった。ありがと。

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://idlysphere.blog66.fc2.com/tb.php/209-16c34654
この記事にトラックバックする(FC2ブログユーザー)

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。