实例方法调用类方法调用实例方法

5

简而言之,如何实现?

我有一个视图控制器,它创建了一些自定义对象。其中一个对象需要调用控制器中的一个方法。该对象似乎想要调用控制器中的类方法,这可能没问题,但是控制器中的类需要调用控制器中的实例方法,而它似乎不想这样做。明白我的意思吗?

如果不明白,这里是伪代码:


ViewController.m

#import "customObj.h"
-(void)viewDidLoad{
  foobar=@"string";//declared in ViewController.h
}
-(void)createObj{
  foobar=@"different string";
  customObj *customObjInstance=[[customObj alloc] init];
}

---

customObj.m

#import "ViewController.h"
-(void)callBack{
  [ViewController createObj];
}

好的,当callBack运行时,它会出现错误,说它正在寻找+createObj(而不是-createObj)。我可以将createObj更改为类方法,但是它会因为foobar在-viewDidLoad中初始化而出现问题,我无法将其更改为+viewDidLoad。也许我可以将foobar移出到一个类方法中,但是如何调用它呢?我不能使用self,我需要使用[ViewController ...]吗?我认为这样不起作用。
我的猜测是我缺少一些基本概念,这并不像我想象的那么困难。我会感激任何能帮我理清思路的人。
非常感谢。
2个回答

5

没有单一正确的答案;它取决于您的自定义对象如何与控制器交互。大多数UIKit视图使用“目标-动作”模式与控制器通信,而许多模型对象则使用委托模式。使用哪种取决于您的控制器和自定义对象的具体情况。

然而,从机械上讲,您可能需要通过自定义初始化程序传递指向您的ViewController的指针,就像这样:

customObj *customObjInstance = [[customObj alloc] initWithController: self];

如果您这样做,请确保您的customObj与控制器紧密耦合是有意义的。


嗯...谢谢。我以前传递过指针,但它看起来像是一个笨拙的方法,我无法想象这是正确的方法。那么一个对象没有对创建它的对象的引用吗?我曾经使用过其他语言,它们有类似于“parent”的东西,它与对象的超类不同。如果我有一个创建uitableview对象的uiview对象,那么该tableview对象没有任何对生成它的uiview实例的引用?这个遗漏是我一直在遇到的问题。再次感谢。 - Eric Christensen
视图具有“超级视图”的概念,即它们所包含的视图,但没有“创建对象”的一般概念。通常,您决定控制器对象与模型对象之间的关系。例如,在您的情况下,您可能会决定customObj实例需要另一个对象来为其创建更多对象,并且您可以使用委托来建模(它本质上是指向另一个对象的指针,但它更通用)。有各种各样的方法可以做到这一点,最好的方法取决于您的具体情况。 - John Calsbeek
如果你想让一个对象拥有"父级(parent)",你可以为其分配一个。一般来说,我并不觉得我需要这样特定的耦合。 - Chuck

3
你可能已经向我提到了类、实例和类之间的各种不同,但如果你的意思只是控制器需要创建能够调用控制器(以创建更多相同的对象)的对象,那么我可以帮助你。
我经常使用委托模式来完成这个任务,就像John所提到的那样:
为从对象到控制器的调用定义一个协议: callBack
//  CallBackDelegate.h


#import <Foundation/Foundation.h>

@protocol CallBackDelegate<NSObject>
- (void)callBack;
@end

在控制器的头文件中,我导入了协议。
#import "CallBackDelegate.h"

并指定控制器实现此协议:

@interface MyViewController : UIViewController < CallBackDelegate > 
{ ...   

同时,在自定义对象类头文件中也要导入该协议。
#import "CallBackDelegate.h"

并添加一个符合协议的实例成员:

id<CallBackDelegate> delegate;

还有一个属性,必须为assign而不是retain,否则会出现循环引用的情况,控制器和自定义对象将相互保留,这意味着它们永远不会被释放。

@property(assign) id<CallBackDelegate> delegate;  

(此成员不必称为委托)

然后确保当您的视图控制器创建自定义对象时,将其自身设置为委托。

customObject.delegate = self; 

然后在您的自定义对象中,您可以安全地执行以下操作:

[ delegate callBack];

希望有所帮助, 马特
如果您搜索苹果的示例代码,您会找到类似以下内容的示例:
[ delegate touchesEnded:touches withEvent:event];
当然,如果您想让该方法将创建的对象的ID传递给您,则该方法不需要像我的示例那样返回(void)。
如果您愿意,您可以编写一个init方法,该方法接受像约翰建议的委托。
customObj *customObjInstance = [[customObj alloc] initWithController:self];
在initWithController中,您传入的控制器需要被分配为委托。

实际上,委托是在许多Objective-C中广泛使用的一种常见模式 - 协议是使其易于实现的关键。 - Kendall Helmstetter Gelner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接