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 中,每个方法声明都必须在 inside@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

我的解决方案是将课程分为两部分:

@interface MyClass
@end

@implementation MyClass
@end

@interface MyClass (Internal)

-(void)internalMethod;

@end

@implementation MyClass (Internal)

-(void)internalMethod {
}

@end

并包括MyClass+Internal.h从两者MyClass.mMyClass+SomeFunctionality.m

于 2013-05-02T18:19:27.820 回答
1

类别无权访问类的私有方法。这与尝试从任何其他类调用这些方法没有什么不同。至少如果您直接调用私有方法。由于 Objective-C 是如此动态,您可以使用其他方式调用私有方法(这是一个坏主意),例如 usingperformSelector或 with NSInvocation

同样,这是一个坏主意。类实现的更新可能会破坏您的类别。

编辑:现在发布了代码-

由于该+storeKitItems方法未在 .h 文件中声明,因此没有类别或其他类可以访问私有方法。

于 2013-05-02T18:05:47.317 回答
0

在您的类别实现文件中,您可以定义该方法的非正式协议

@interface YourClasses (ExternalMethods)

+(NSDictionary*) storeKitItems;

@end

这将阻止编译器抱怨不知道您类别中的方法 storeKitItems。

于 2013-05-02T19:12:09.187 回答