3

Objective-cに奇妙な問題があります。コードは次のとおりです。

STViewController.h

#import <UIKit/UIKit.h>
@interface STViewController : UIViewController <UIAlertViewDelegate>
+(void)myStaticMethod;
@end

STViewController.m

#import "STViewController.h"

@implementation STViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [STViewController myStaticMethod];
}

+ (void)myStaticMethod {
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Foo bar"
                                                    message:@"baz bat"
    //what does self even mean in this context? The class object STViewController?
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:@"OK", nil];
    [alert show];
    [alert release];
}

#pragma mark UIAlertViewDelegate

// TRICKY PART if it's static it works, if it's not, it doesn't.
// even though the protocol declares instance methods (with a minus).
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    NSLog(@"It works!");
}

@end

なぜこれが起こるのですか?これは正しいです?エラーや警告は表示されません。プロトコルメソッド宣言の-/+は何かをしますか?

4

3 に答える 3

2

クラス内のメソッドselfは、クラスオブジェクトを参照します。NSObjectクラスオブジェクトは、クラスに送信されたメッセージ(クラスメソッド、「+」が付いたもの)を受信する通常のobjcオブジェクト(から派生)です。

あなたの場合、クラスオブジェクトをのデリゲートとして使用しましたUIAlertView(これは、UIAlertViewのAPIが静的タイプのオブジェクトを明示的に必要としないために機能しますid<UIAlertViewDelegate>)。これで、アラートビューは、デリゲートメッセージをクラスオブジェクトに送信するだけで、クラスメソッドとして実装したため、これも問題ありません。

于 2013-02-26T09:41:04.663 に答える
1

まず、Class(通常はから取得する[MyClass class])オブジェクトも有効なObjCオブジェクトであることを知っておく必要があります。これは、クラスオブジェクトにもメッセージを送信できることを意味します。

例えば

@interface MyClass : NSObject
+ (NSString *)name;
@end

@implementation MyClass
+ (NSString *)name {
    return NSStringFromClass(self); // note in class method, self == [MyClass class]
}
@end

// ------- in some method

id cls = [MyClass class]; // the correct type should be Class, but since Class is an object, id will also work
NSLog(@"%@", [cls name]); // call like instance method - MyClass
NSLog(@"%@", [MyClass name]); // call like class method - MyClass

したがって、クラスオブジェクトを他のオブジェクトと同じように使用し、インスタンスメソッドのようにクラスメソッドを呼び出すことができます。

そしてクラスメソッドは実際にはインスタンスメソッドです!! 違いは、クラスメソッドがのクラスであるメタクラスのインスタンスメソッドであるということですClass。メタクラスの詳細については、http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.htmlをご覧ください。


また、メタクラスにプロトコルを追加することは(少なくともコンパイラ時では)不可能であるため、クラスインターフェイスが正しくありません。したがって、そうすると[self conformsToProtocol:@protocol(UIAlertViewDelegate)]NOが返されます。+ alertView:clickedButtonAtIndex:ただし、このメソッドをメタクラスのインスタンスメソッドとして追加する実装を行ったため、デリゲートコードは機能し、 [self responseToSelector:@selector(alertView:clickedButtonAtIndex:)]YESを返します。

于 2013-02-26T09:44:44.743 に答える
-3

動的なアラートデリゲートとして設定していますがself、静的なメソッド呼び出しは、そもそも間違っているため+ (void)myStaticMethod、将来いつか呼び出すと、初期化されselfていない可能性がありますnil。そのため、未定義の動作だけでなく、他のエラーが続く可能性があります

于 2013-02-26T09:26:22.600 に答える