3

私はUILabela で an をサブクラス化していCustomLabel classます。シンプルを使用しようとすると問題が発生UILabelし、将来的に他の要素をサブクラス化したいと考えています。categoryのを作成できることを読みましたUILabel。これのどれが良いですか?カテゴリまたはサブクラス?

これがサブクラス化しようとしている私のコードです。メソッドで失敗しますsetFont

@interface WPCustomLabel : UILabel

@property (strong, nonatomic) UIColor *color;
@property (strong, nonatomic) UIFont  *font;

@end

#import "WPCustomLabel.h"

@implementation WPCustomLabel

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        [self setBackgroundColor:[UIColor clearColor]];

    }
    return self;
}

-(void)setColor:(UIColor *)color
{
    self.color = color;
}

-(void)setFont:(UIFont *)font
{
    self.font = font;
}

@end

ViewController でこれを CustomLabel と呼びます。

@property (strong, nonatomic) WPCustomLabel *titleLbl;

titleLbl = [[WPCustomLabel alloc] initWithFrame:CGRectMake(75, 25, 200, 14)];
[titleLbl setTextColor:[UIColor blackColor]];
[titleLbl setFont:[UIFont systemFontOfSize:14]];
[titleLbl setBackgroundColor:[UIColor clearColor]];
[titleLbl setText:@"Here I AM"];
[self.view addSubview:titleLbl];
4

4 に答える 4

3

UILabel、UIButton などの UI 要素をサブクラス化する方法

決して〜ない。

のカテゴリを作成できることを読みましたUILabel

それは正しい。実際、クラスを拡張したい場合は、代わりにカテゴリを使用する必要があります (前の回答を参照)。

setFont メソッドで失敗します。

どのように「失敗する」かは述べていませんが、推測できるのは、結果として無限再帰とスタックオーバーフロー/セグメンテーション違反が発生することだけです。だって

self.font = font;

と同等です

[self setFont:font];

したがって、無条件にメソッド自体からメソッドを呼び出しています。

これらのプロパティの動作をカスタマイズする必要がない場合は、そのままにしておいてください。:) もしそうなら、完了したらスーパークラスの実装を呼び出すだけです:

- (void)setFont:(UIFont *)font
{
    [self doScaryCustomMagicStuff];
    [super setFont:font];
}
于 2013-10-30T15:07:14.183 に答える
3

それは本当にあなたが達成しようとしているものに依存しますが、カテゴリはプロパティを持つことができないので、あなたの例では機能しません。

ここでの問題は、セッターでセッターをリコールしていることです。

-(void)setFont:(UIFont *)font
{
    self.font = font;
}

にコンパイルされます (と同じです):

-(void)setFont:(UIFont *)font
{
    [self setFont:font];
}

この問題を見ることができるはずです。一度呼び出すと、このメソッドから抜け出すことはできません。ここでプロパティとインスタンス変数を混​​同しています。セッターのオーバーライドは、プロパティを介して設定するのではなく、インスタンス変数に直接設定する必要があります。そう:

// LOOK AT EDIT -- Do not do this for 'font'
-(void)setFont:(UIFont *)font
{
    _font = font;
}

編集:

私は正直に考えていませんでした。サブクラス化UILabelしているため、すでにfontプロパティがあります。UILabelスーパークラス ( ) にすでにあるため、これを直接指定しないでください。したがって、そのプロパティ宣言を取り除きます。そうは言っても、color必要ない場合は、おそらくカテゴリの方が適しているでしょう。setFont:とにかく、次のようにメソッドをオーバーライドできます。

-(void)setFont:(UIFont *)font
{
    [super setFont:font];
    // do custom stuff
}

colorはプロパティではないため、UILabelインスタンス変数を介して設定する必要があります (上記のように) 。 は応答しないため_color = color、このセッターで super を呼び出さないでください。UILabel

あなたはそのサブクラスであるため、super呼び出しはの実装を呼び出しています。UILabel

于 2013-10-30T15:09:55.283 に答える
0

アイテムの機能を拡張したい場合は、カテゴリを使用する必要があります。アプリケーション内の任意の UILabel が実行できる関数を UILabel に追加するようなものです。

ただし、アプリのいくつかの場所で同様の UILabels が必要な場合は、UILabel をサブクラス化するよりも、initWithFrame または awakeFromNib 内でそれに応じて変更し、必要な場所でカスタム実装を使用してください。

あなたの場合、サブクラス化することをお勧めします。SetFont メソッドは標準の UILabel に既に存在し、setColor の代わりに setTextColor を使用できます。

于 2013-10-30T15:06:04.827 に答える