Objective-C类别财产未被确认

时间:2014-03-27 14:09:40

标签: ios objective-c xcode

我需要在一个视图中使用多个表并识别每个表,我已经在UITableView上添加了一个名为" tableID"

的属性的类别

这是类别代码

·H

#import <UIKit/UIKit.h>
@interface UITableView (BrandsTView)
@property (nonatomic,strong) NSString *tableID;
@end

的.m

#import "UITableView+BrandsTView.h"
@implementation UITableView (BrandsTView)
@dynamic tableID;
@end

在视图控制器的初始化代码中,我按如下方式设置属性:

[self.hubTableView setTableID:@"tblHubBrands"];

当代码到达第一个表视图委托方法时,tableID无法识别,并且在尝试按如下方式设置tblID时出错:

注意:此时代码完成时可以使用tableID,因此再次假设它将被识别

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    NSString *tblID = [tableView tableID]; // error: unrecognized selector
    if([tblID isEqualToString:@"tblHubBrands"]){
        return [hubBrands count];
    } else {
        //
    }
}

知道这里发生了什么吗?我假设tableID属性应该在导入该类别的任何类中可用。

谢谢!

5 个答案:

答案 0 :(得分:2)

  

类别可用于声明实例方法或类   方法,但通常不适合声明额外的   属性。在a中包含属性声明是有效的语法   类别界面,但无法声明其他内容   类别中的实例变量。这意味着编译器不会   合成任何实例变量,也不会合成任何属性   存取方法。您可以在中编写自己的访问器方法   类别实现,但你将无法跟踪a   该属性的值,除非它已经由原始存储   类。

     

添加由新实例支持的传统属性的唯一方法   变量到现有类是使用类扩展,如   在“类扩展扩展内部实现”中描述。

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

答案 1 :(得分:1)

正如其他人所指出的那样,您无法将实例变量添加到类别中的类中。

我已经解决了在运行时使用指向表视图的指针来管理多个表视图的问题。我将指向两个表视图的指针保存为IBOutlets,然后在我的代码中保存表视图数据源和委托方法(它们都将指向表视图的指针作为它们的第一个参数)我检查看哪个表视图正在调用我和相应地采取行动。

e.g:

VC的标题可能包含以下内容:

@interface MyTwoTableViewVC: UIViewController;
{
  IBOutlet UITableView* firstTableView;
  IBOutlet UITableView* secondTableView;
}
@end

数据源方法的实现可能如下所示:

@implementation MyTwoTableViewVC
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  if (tableView == firstTableView)
     //return the number of rows in section for the first table view
  else if (tableView == secondTableView)
     //return the number of rows in section for the second table view
  else
     //error. We only have 2 table views!
}

此方法实质上使用表视图的地址作为其ID。在运行时,表视图的地址不会改变,因此效果很好。

如果您决定将ID属性添加到类别中的表视图中,则可以像您一样定义@dynamic属性,然后编写使用关联存储来读取/写入ID的自定义getter和setter运行时对象的值。这有点像黑客,对这个问题有点矫枉过正,但它确实有效。

您要查看的方法是objc_getAssociatedObject()和objc_setAssociatedObject()。

我在github上有associative storage demo project(这是该项目的链接。)

(该项目使用一类NSObject在运行时向任何NSObject添加关联存储支持。)

答案 2 :(得分:0)

那是因为tableID上没有声明UITableView方法。你做了什么,是声明一个属性,然后使用@dynamic告诉编译器,该属性的访问器方法是在别处实现的,但实际上没有实现。

此外,您无法使用类别(您需要添加工作属性)向对象添加新的ivars。我推荐继承。

答案 3 :(得分:0)

UITableView继承自UIView 只需将tag属性设置为每个属性的唯一属性即可。 更好的是,使用NS_ENUM定义您自己的命名常量以用于标记。 您可以将枚举放在全局常量.h文件中并将其导入任何位置。 现在,您可以通过代码完成和可读代码轻松快速地识别标识符。 如果你需要一个字符串值来显示一个很容易根据检查标签的简单switch语句返回字符串的地方。 您甚至可以使用可本地化的字符串函数返回字符串。

答案 4 :(得分:0)

您可以使用关联对象向类别添加属性。您可以阅读更多here 话虽这么说,在你的情况下,你应该遵循其他答案的建议。