5

オープン ソース プロジェクトの機能を拡張しようとして、新しいメソッドを追加するためのカテゴリを作成しました。この新しいメソッドでは、カテゴリは元のクラスの内部メソッドにアクセスする必要がありますが、コンパイラはそのメソッドが見つからない (もちろん内部メソッドです) と言います。このメソッドをカテゴリに公開する方法はありますか?

編集

元のコードを変更したくないので、元のクラス ヘッダー ファイルで内部メソッドを宣言したくありません。

コード

元のクラス実装ファイル (.m) には、次のメソッド実装があります。

+(NSDictionary*) storeKitItems
{
  return [NSDictionary dictionaryWithContentsOfFile:
          [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
           @"MKStoreKitConfigs.plist"]];
} 

カテゴリに、次のメソッドを追加します。

- (void)requestProductData:(NSArray *(^)())loadIdentifierBlock
{
    NSMutableArray *productsArray = [NSMutableArray array];
    NSArray *consumables = [[[MKStoreManager storeKitItems] objectForKey:@"Consumables"] allKeys];
    NSArray *nonConsumables = [[MKStoreManager storeKitItems] objectForKey:@"Non-Consumables"];
    NSArray *subscriptions = [[[MKStoreManager storeKitItems] objectForKey:@"Subscriptions"] allKeys];
    if(loadIdentifierBlock != nil) [productsArray addObjectsFromArray:loadIdentifierBlock()];
    [productsArray addObjectsFromArray:consumables];
    [productsArray addObjectsFromArray:nonConsumables];
    [productsArray addObjectsFromArray:subscriptions];
    self.productsRequest.delegate = self;
    [self.productsRequest start];
}

storeKitItemsコンパイラーを呼び出すすべての行で、「クラスメソッド "+storeKitItems" が見つかりません...

4

3 に答える 3

5

これは簡単です。メソッドの前方宣言を行います。

残念ながら、obj-c では、すべてのメソッド宣言は 内にある必要があるため、別の内部カテゴリを使用してカテゴリ ファイルで@interface機能させることができます。.m

@interface MKStoreManager (CategoryInternal)
   + (NSDictionary*)storeKitItems;
@end

実装は必要ありません。これは、@dynamicプロパティと同様に、メソッドが別の場所にあることをコンパイラに伝えるだけです。

警告を削除することのみに関心がある場合は、クラスを にキャストすることもできます。id次の方法も機能するはずです。

NSDictionary* dictionary = [(id) [MKStoreManager class] storeKitItems];

ただし、私のお気に入りの解決策は、少し異なる方法で行うことです。次の例を想定してみましょう。

@interface MyClass
@end

@implementation MyClass

-(void)internalMethod {
}

@end

@interface MyClass (SomeFunctionality)
@end

@implementation MyClass (SomeFunctionality)

-(void)someMethod {
  //WARNING HERE!
  [self internalMethod];
}

@end

私の解決策は、クラスを 2 つの部分に分割することです。

@interface MyClass
@end

@implementation MyClass
@end

@interface MyClass (Internal)

-(void)internalMethod;

@end

@implementation MyClass (Internal)

-(void)internalMethod {
}

@end

MyClass+Internal.hとの両方MyClass.mから含めるMyClass+SomeFunctionality.m

于 2013-05-02T18:19:27.820 に答える
1

カテゴリは、クラスのプライベート メソッドにアクセスできません。これらのメソッドを他のクラスから呼び出そうとするのと同じです。少なくとも、プライベート メソッドを直接呼び出す場合。performSelectorObjective-C は非常に動的であるため、または を使用するなどの他の手段を使用してプライベート メソッドを呼び出すことができます (これは悪い考えです) NSInvocation

繰り返しますが、これは悪い考えです。クラスの実装を更新すると、カテゴリが壊れる可能性があります。

編集:コードが投稿されたので-

+storeKitItemsメソッドは .h ファイルで宣言されていないため、カテゴリや他のクラスはプライベート メソッドにアクセスできません。

于 2013-05-02T18:05:47.317 に答える