【问题标题】:Calling NSObject superclass method with [self performSelector:@selector]?使用 [self performSelector:@selector] 调用 NSObject 超类方法?
【发布时间】:2012-10-06 16:46:40
【问题描述】:

我有一个 NSObject 的子类,我想在其中立即调用(一种 -(void)viewDidLoad)方法(在这种情况下加载 MkMapView):有什么更好的方法呢?我想我不能使用 viewDidLoad,所以我可以使用 performSelector 吗?

SubClass.h

@interface Mysubclass : NSObject <MKMapViewDelegate> {
}

SubClass.m(第一种选择)

-(id)init{
 self = [super init];
 if ( self != nil ) {
 // THE CODE TO INITIALIZE MKMAPVIEW
}
return self
}

或 SubClass.m(第二选择)

-(id)init{
 [self performSelector:@selector(myMethod)];
 return self;
}

-myMethod{
 // THE CODE TO INITIALIZE MKMAPVIEW
}

什么是更好(或正确)的选择?可以避免-(id)init 吗?或者每次我添加一个子类时,要调用一个方法我必须将它写入-(id)init?谢谢!

【问题讨论】:

  • 为什么不直接调用那个方法呢? [self myMethod];
  • 顺便说一句,省略函数的返回类型并不是一个好习惯。
  • 我认为你应该从一本好的编程入门书开始。
  • 谢谢 DrummerB,我已经试过了,问题在我对 Nate 的回答中...

标签: objective-c xcode methods


【解决方案1】:

在这种情况下没有理由使用-performSelector:。如果您想添加一个在创建对象时初始化 MKMapView 的方法,请从 if (self) 块中调用该方法:

- (id)init
{
    self = [super init];
    if (self) {
        [self setupMapView];
    }
    return self;
}

- (void)setupMapView
{
    // THE CODE TO INITIALIZE MKMAPVIEW
}

是否有第二种方法-setupMapView 或简单地将设置MKMapView 的代码留在-init 方法的if (self) 块中或打破将代码转换为从-init 调用的第二个方法-setupMapView

话虽如此,听起来您的设置可能会出现其他问题。您的 MKMapView 应该 [最有可能] 在 UIViewController 子类中(可能有一个关联的 XIB),因此您将可以访问 -viewDidLoad。请注意,您的 UIViewController 子类将作为您的 MKMapView 的代表。

更新 1

在您的UIViewController 子类实例中(我假设您将其称为ViewController,您应该有一个IBOutlet 到一个MKMapView 对象。在ViewController.h 中通过(1)添加一个实例变量

@interface ViewController : UIViewController
{
    IBOutlet MKMapView *myMap;
}
@end

或通过 (2) 添加 属性

@interface ViewController : UIViewController
@property (nonatomic, strong, readwrite) IBOutlet MKMapView *myMap;
@end

现在在 Interface Builder 中打开 ViewController.xib。您应该在视图中有一个MKMapView。如果您还没有,请从对象库中添加一个。右键单击File's Owner。找到包含项目myMap 的行。从行右端的圆圈拖动到可见视图中的MKMapView

您的ViewController 类现在有了MKMapView 的出口。加载后,您将能够向视图控制器视图的 MKMapView 子视图发送消息。

您应该为您的SubClass 实例提供一个属性或实例变量,这样它就不会在-viewDidLoad 返回时立即被销毁。通过将实例变量添加到 ViewController.h

再次执行此操作
@interface ViewController : UIViewController
{
    IBOutlet MKMapView *myMap;
    SubClass *istance;
}
@end

或通过添加属性

@interface ViewController : UIViewController
@property (nonatomic, strong, readwrite) IBOutlet MKMapView *myMap;
@property (nonatomic, strong, readwrite) SubClass *istance;
@end

现在,在ViewController.m 中,您需要定义-viewDidLoad,以便将self.istance 设置为self.myMap 的代理。在 cmets 中,我曾建议创建自己的初始化程序 -initWithMapView:。如果您打算让SubClass 对您的MKMapView 进行一些广泛的设置,那是有道理的。如果您只想让SubClass 成为MKMapView 的代表,则不需要这样的方法。

让我们考虑两种情况:

(1)使用-[SubClass initWithMapView:]的方法:

ViewController.m 中,您将拥有(在ViewController@implementation 内)

- (void)viewDidLoad
{
    self.istance = [[SubClass alloc] initWithMapView:self.myMap];
}

SubClass.h 中,您将拥有(在SubClass@interface 内)

- (id)initWithMapView:(MKMapView *)mapView;
@property (nonatomic, weak, readwrite) MKMapView *mapView;

SubClass.m 中,您将拥有(在SubClass@implementation 内)

- (id)initWithMapView:(MKMapView *)mapView
{
    self = [super init];
    if (self) {
        self.mapView = mapView;
        self.mapView.delegate = self;
        //more setup of mapView.
    }
    return self;
}

(2) 使用-[SubClass init]:

相反,在ViewController.m 你将拥有

- (void)viewDidLoad
{
    self.istance = [[SubClass alloc] init];
    self.myMap.delegate = self.istance;
}

【讨论】:

  • 感谢您的回答,Nate,感谢您的好意,我知道我是初学者,但我们始终感谢您的帮助和耐心。我已经尝试过你的技巧,但是我必须调用 -(id) init 的精确方法是 -(void)mapViewWillStartLoadingMap:(MKMapView *) {},所以如果我写 [self mapViewWillStartLoadingMap:self] XCode 会给出一个问题: “不兼容的指针类型将'SubClass'发送到'MKMapView *'类型的参数”和方法在创建我的对象时不会初始化MKMapView。正确的表达方式是什么?谢谢!
  • 听起来您应该将自己指定的初始化程序 initWithMapView: 添加到您的类 SubClass 并传递您希望您的 SubClass 实例成为其代表的 MKMapView。然后,从initWithMapView: 调用mapViewWillStartLoadingMap:,将MKMapView 参数传递给initWithMapView:
  • 话虽如此,听起来您可能误解了-mapViewWillStartLoadingMap: 方法的用途。通常,该方法由MKMapView 的实例在已设置为MKMapViewdelegate 的对象上调用。为此,在- (id)initWithMapView:(MKMapView *)mapViewif (self) 块中写入[mapView setDelegate:self];。然后,当MKMapView 开始加载地图时,它会在您的SubClass 实例上调用mapViewWillStartLoadingMap: 方法。
  • 但我必须在我的 SubClass 或 SUBSTITUTE -(id)init 方法中添加另一个 - (id)initWithMapView:(MKMapView *)mapView ?谁调用 -(id)initWithMapView?它“使用指定的地图视图初始化一个新创建的栏按钮项”,但我没有按钮!
  • 您将在SubClass.h 中声明并在SubClass.m 中定义一个新方法-(id)initWithMapView:(MKMapView *)mapView。这是你自己的方法。顺便说一句,这也是MKUserTrackingBarButtonItem 上的一个方法的名称,但你的类和那个类都具有相同名称的方法并不重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2011-02-10
  • 2010-12-02
  • 1970-01-01
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多