尝试从开源项目扩展功能,我写了一个类别来添加一个新方法。在这个新方法中,类别需要从原始类访问内部方法,但编译器说它找不到方法(当然是内部的)。有没有办法为类别公开此方法?
修改
我不想修改原始代码,所以我不想在原始类头文件中声明内部方法。
代码
在原始的类实现文件(.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”未找到...
答案 0 :(得分: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
我的解决方案是将课程分为两部分:
@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
答案 1 :(得分:1)
类别无法访问类的私有方法。与尝试从任何其他类调用这些方法没有什么不同。至少如果你直接调用私有方法。由于Objective-C是如此动态,您可以使用其他方法调用私有方法(这是一个坏主意),例如使用performSelector
或NSInvocation
。
同样,这是一个坏主意。对类的实现的更新可能会破坏您的类别。
编辑:现在已发布代码 -
由于.h文件中未声明+storeKitItems
方法,因此任何类别或其他类都不能访问私有方法。
答案 2 :(得分:0)
在您的类别实现文件中,您可以为方法
定义和非正式协议@interface YourClasses (ExternalMethods)
+(NSDictionary*) storeKitItems;
@end
这将阻止编译器抱怨你不知道你类别中的方法storeKitItems。