12

クラス拡張のUITableViewにプロパティを追加したいと思います。

@interface UITableViewController ()

@property NSString *entityString;

@end

次に、拡張機能をインポートしてから、UITableViewControllerのサブクラスでentityStringプロパティを使用します。

@implementation CustomerTableViewController

- (void)viewDidLoad {
    self.entityString = @"Customer";
    ...
    [super viewDidLoad];
}
...

Appleのドキュメントによると:

コンパイラは、プライマリクラスの実装内で関連するアクセサメソッド(...)を自動的に合成します。

しかし、それを実行しようとすると、次のエラーが発生します。

-[CustomerTableViewController setEntityString:]:認識されないセレクターがインスタンス0x737b670に送信されました

私は何が間違っているのですか?サブクラスからプロパティにアクセスできない可能性がありますか?

4

3 に答える 3

16

代わりに、連想参照のあるカテゴリを使用してみてください。これははるかにクリーンで、UIButtonのすべてのインスタンスで機能します。

UIButton+Property.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSObject *property;

@end


UIButton+Property.m

#import "UIButton+Property.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY;

@dynamic property;

-(void)setProperty:(NSObject *)property
{
  objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)property
{
   return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY);
}

@end

//使用例

#import "UIButton+Property.h"


UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.property = @"HELLO";
NSLog(@"Property %@", button1.property);
button1.property = nil;
NSLog(@"Property %@", button1.property);
于 2012-09-03T18:57:57.957 に答える
8

クラス拡張は、追加のインターフェイス(メソッドとプロパティ)を宣言するために使用されます。その実装コントラクトは、クラスのプライマリ内で満たされます@implementation

そのため、クラス拡張を介してストレージを追加したり、ivarを追加したりすることはできません。クラス拡張はインターフェースであり、それ以上でもそれ以下でもありません。 は宣言@synthesize用のストレージを作成するものですが、のはクラスのにのみ表示できます(明示的にまたはコンパイラのデフォルトの動作として)。@property@synthesize@property@implementation

フレームワーククラスを再コンパイルできないため、ivarを追加することはできません。

@prashatの答えは、既存のクラスにストレージを追加する1つの方法です。ただし、そのルートを使用することは一般的に望ましくありません。フレームワーククラスから状態をぶら下げることは、設計が不十分であることを示しており、アプリケーションを長期にわたって維持することが非常に困難になります。

デザインを再検討し、直接含めることができないオブジェクトに状態をアタッチする必要がある理由を理解し、その要件をリファクタリングすることをお勧めします。

于 2012-09-03T19:42:04.670 に答える
5

ドキュメントの状態:

クラス拡張は匿名カテゴリに似ていますが、宣言するメソッドは、対応するクラスのメインの@implementationブロックに実装する必要がある点が異なります。

を使用する場合、アクセサメソッドを宣言@propertyするのとほぼ同じです。つまり、このようなことを実行できるのは、クラスの「メイン」ブロックの作成者でもある場合のみですが、UITableViewControllerでは作成者ではありません。@implementation

ここでの唯一のオプションは、インスタンス変数を追加できないカテゴリです。

ドキュメントのリンク、およびそのページの最後の行に注意してください。

setValue:メソッドの実装は、クラスのメインの@implementationブロック内に表示される必要があります(カテゴリに実装することはできません)。そうでない場合、コンパイラーは、setValue:のメソッド定義が見つからないという警告を出します。

于 2012-09-03T18:55:30.503 に答える