IOS/Objective-C:从类方法中调用常规 self 方法



我有一个类方法,我按以下方式调用:

#import myClass.h;
[MYClass classMethod];
In myClass, I have a method as follows:
+(void)classMethod {
NSLog(@"classMethod called");
[self otherMethod];
}
-(void) otherMethod {
NSLog(@"other method called");
}

但是,这会引发未知的选择器错误。

我的理解是 self 意味着类方法中的文件以外的其他东西,即类本身,我可以通过将 -otherMethod 更改为 +otherMethod 来摆脱该错误。 但是,NSObject 中实际上有许多按顺序调用的方法,所以我宁愿不必将每个方法都更改为 +。

当从类方法中调用方法时,这是您应该做的吗? 还是有自我的替代品?

提前感谢您的任何建议。

在实例方法中,self是对当前类的当前实例的引用。顾名思义,类方法是在类本身而不是实例上调用的,因此没有可供self引用的当前实例。在本例中,self是指当前类。

换句话说,在调用[self otherMethod]的类方法中,调用另一个名为otherMethod的类方法(即用+声明)。要调用实例方法,您需要处理对象的实例,该实例可以传递给类方法,也可以是类方法本身实例化的实例,但您仍然不会使用self引用该实例,您将使用参数或变量名称。

一般来说,这应该不是问题。您需要考虑对象的语义,以及这些方法是否都应该是类方法(即它们不需要对对象的特定实例进行操作),或者它们是否应该是实例方法,如果需要,您的类方法会创建一个新实例,或者您的类方法不应该是类方法。

在这个问题中,至少在术语上存在一些混乱,实际问题尚不清楚。希望以下一些可能会有所帮助。

我的理解是 self 意味着类方法中的文件以外的其他东西,即类本身

变量self从不表示文件,它始终引用调用该方法的对象。类方法和实例方法之间的区别在于调用该方法的对象的类型。

您的示例课程:

@implemention MyClass
{
// any instance variables
}
+ (void)classMethod
{
NSLog(@"classMethod called");
[self otherMethod];
}
- (void) otherMethod
{
NSLog(@"other method called");
}
// ...
@end

定义一个模板,从中创建类对象(其类型(最终)是Class类型的子类)和零个或多个实例对象(类型MyClass)。类对象获取类方法,实例对象获取实例方法,每个对象获取自己的实例变量集。

在代码片段中:

MyClass *anInstance = [MyClass new];
[anInstance otherMethod];

然后anInstance的值,对类型MyClass对象的引用,被传递给otherMethod,并作为self的值提供。在代码片段中:

[MyClass classMethod];

编译器有效地将MyClass替换为对MyClass类对象的单个实例的引用,对象引用,并将其传递给classMethod,在那里它作为self的值可用...换句话说,"调用类方法"是"在类对象上调用实例方法" - 机制是相同的。

变量self从不引用"文件",并且除了它引用的对象成员(实例或类对象)之外,没有直接访问任何其他内容的方法。

特别是类方法中的self不提供对实例方法或变量的访问,因为它们是实例对象的成员,并且self引用类对象。若要在任何地方访问实例方法或变量,都需要实例对象

当从类方法中调用方法时,这是您应该做的吗?还是有自我的替代品?

"替代"是对实例对象的引用。可能有很多实例,并且没有定义类方法可以使用的"默认"语言。这并不奇怪,因为实例的一个重要特征是它的身份- 在典型的应用程序中,有许多数组(NSArray),具有不同的内容,不同类型的数组,用于不同的目的,每个数组都与其他数组不同,即具有唯一的身份和方法被调用到该特定个人(也称为实例)传递信息。

从您的陈述来看,您可能追求的是这样的:

+ (void)classMethodUsingInstance:(MyClass *)someInstance
{
NSLog(@"classMethod called");
[someInstance otherMethod];
}

这是出于某种原因,您需要一个可以与特定实例交互的类方法,因此将其作为参数传递。然而,这就提出了一个问题,为什么这不仅仅是一个实例方法......

有没有更好的方法可以从视图控制器运行大量复杂的代码,而无需将其放入VC中? classMethod 恰好是与使用大量属性和大量方法的服务器的同步操作。如果可能的话,我不想把它放在调用该方法的 VC 中,因为那个 VC 已经管理了很多......[来自评论]

这个评论听起来像你的classMethodotherMethod在不同的类中,后者在你的视图控制器类中,前者除了"我不想把它放在VC中"之外,你没有指定它的位置。如果是这种情况,上面的大纲将 VC 的实例传递给其他地方定义的方法可能是您需要的。也就是说,你有一些大型的复杂进程,它在VC上运行,而不是VC的一部分,所以你在另一个类中定义这个过程 - 作为最适合设计的实例或类方法 - 并将VC实例传递给它。

这不仅仅是一个标准模型,而是一个基本模型(例如,想想你编写的所有代码,它使用数组和字典,但不是数组或字典的一部分!),这就提出了一个问题,为什么你会有问题并首先提出这个问题......所以也许你在问别的东西...

它不能是实例方法,因为它需要从不同的视图控制器类调用。 [来自评论]

也许我需要创建一个名为 sharedInstance 的类的属性,然后我可以使用[self sharedInstance].property[[self sharedInstance] method]访问该类的属性和方法。[来自以下评论]

结合之前的"不在VC中"的评论,现在听起来像:

  • 您希望在类A上调用方法M;
  • 该方法需要在B的特定实例上运行;
  • 调用应该来自不同类N的方法C;和
  • 该方法N没有对传入其调用所需的特定实例的引用BM

如果正确意味着是,您可能需要一个共享实例模型B.

希望这有所帮助,而不仅仅是混淆!

最新更新