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是指类对象。类对象是一个普通的 objc 对象(派生自NSObject),它将接收发送给类的消息(类方法,那些带有“+”的方法)。

在您的情况下,您将类对象用作 a 的委托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 回答