0

attributedTextUILabel と UITextView のプロパティを操作するメソッドを定義する UIView カテゴリがあります。

@implementation UIView (replaceAttrText)
-(void) replaceAttrText: (NSString *)str {
    if ([self respondsToSelector: @selector(setAttributedText)]) {
        NSMutableAttributedString *labelText = [self template];

        // change it

        [self performSelector:@selector(setAttributedText) withObject: labelText];
    }
}
@end

RespondsToSelector は、UILabel と UITextView の両方に対して false を返し (ただし、setAttributedText に応答します)、setAttributedText がrespondsToSelectorチェックなしで直接実行されると、例外が発生します。

カテゴリが UILabel に (セレクターなしで) 直接実装されている場合、すべてが機能しますが、残念ながら UILabel と UITextView には attributedText プロパティを持つ共通の祖先がありません。

私は何を間違っていますか?ありがとう!

4

2 に答える 2

5

UILabelという名前のメソッドがありUITextViewませんsetAttributedText。しかし、彼らには という名前のメソッドがありsetAttributedText:ます。コロンに注意してください。コロンはメソッド名の一部です。それがあるかどうかは、2つの完全に異なる方法を表しています。

コードを次のように変更します。

-(void) replaceAttrText: (NSString *)str {
    if ([self respondsToSelector: @selector(setAttributedText:)]) {
        NSMutableAttributedString *labelText = [self template];

        // change it

        [self performSelector:@selector(setAttributedText:) withObject: labelText];
    }
}

つまり、 への両方の参照にコロンを追加しsetAttributedTextます。

于 2013-05-18T20:31:17.220 に答える
3

@maddy には正しい具体的な答えがあります。これは、アンチパターンと見なされるものに対処します。

一般に、カテゴリを使用して Apple 提供のクラスを拡張しないでください。これは、コードがシステム フレームワークと効果的に絡み合っていることを意味します。これにより、独自のクラスを処理するだけでなく、コードをリファクタリングする必要が生じるため、メンテナンスと拡張がより困難になります。コードは、絡み合って、拡張する両方のクラスのパターンで実装されます。およびそれを使用するクラス。

これが、Apple が通常、この種のパターンを推奨しない理由です。Apple クラスを拡張する場合は、既存のメソッドをオーバーライドしてはなりません (実装の詳細が壊れます)。また、OS の将来のリリース (更新であっても) に、次のようなメソッドが含まれないように、常にメソッドの前にプレフィックスを付ける必要があります。あなたのものと衝突します(それは以前に起こりました-addObjectIfAbsent:そのNSMutableArrayようなイベントが最も注目に値するものでした)。

同様に、チェックの動作が時々動作し、動作しないこともあり、isKindOfClass:respondsToSelector:のアンチパターンです。適切に設計されたアプリケーションでは、通常、あまりにも一般的な型を渡すことを避ける必要があります。そのため、型の受信者は、その型を操作する前にそれが何であるかを把握する必要があります。これを行うと、特にコードの正確性を再確認するコンパイラの機能が無効になります。

属性付きテキストを必要とする UI オブジェクトには何らかの手段でアクセスし、そうでないものには別の手段でアクセスできるように、アプリケーションをリファクタリングすることをお勧めします。つまり、どんな呼び出しでreplaceAttrText:も (また、Objective-C では、略語はめったに使用されません。IDE の補完により、何かを入力する必要がほとんどなくなり、略語がないことでコードが明確になります) は、本当に必要なオブジェクトに対してのみ実行されます。それらの属性テキストが調整されました。ユーザー インターフェイスを動的またはプログラムで生成している場合、たとえば、モデルとこれを処理するビューの間にコントローラー オブジェクトがある場合があります。

于 2013-05-19T18:08:49.250 に答える