如何使用 name 而不是 self.name 访问 Objective-C @property

问题描述 投票:0回答:1

TL;DR 正确的做法是访问 Objective-C

@property (...) foo
作为
foo
而不是
self.foo

详情:

我的一个 iOS 项目仍然使用我几年前编写的一些 Objective-C 代码。

// SomeObject.h
@interface SomeObject : NSObject
@property (nonatomic, readonly) NSString *foo;
@end

// SomeObject.m
@implementation SomeObject { ... }
@synthesize foo;

- (void)someMethod {
   foo = @"bar";
}

- (void)otherMethod {
   NSLog(@"Foo: %@", foo);  // ---> "bar"
}
@end

这按预期工作得很好。现在我想使用 getter 来访问一些新的 Swift 代码,而不是手动设置

foo

// SomeObject.m
@implementation SomeObject { ... }
@synthesize foo;

- (NSString *)foo {
   return [SwiftObject getFoo];
}

- (void)otherMethod {
   NSLog(@"Foo: %@", foo);  // ---> nil
   NSLog(@"Foo: %@", self.foo);  // ---> "swiftBar"
}
@end

因此,仅当使用

self.foo
而不是仅使用
foo
时,使用 getter 才可以正确使用。这不是一个大问题,但需要将现有代码中所有使用的
foo
替换为
self.foo

有没有一种干净的方法来避免这种情况,使用

foo
getter 并仍然使用
foo
而不是
self.foo

ios objective-c
1个回答
0
投票

TL;DR 正确的做法是访问 Objective-C

@property (...) foo
作为
foo
而不是
self.foo

在没有目标的情况下,不可能使用裸名称访问 Objective-C 属性(即没有

self.
)——这是因为
@property
是在类型上生成 getter + setter methods
的简写,并且方法调用总是需要调用一个对象。

相反,您的第一个代码片段出于不相关的原因而工作:

  • 默认情况下,声明一个裸的
    @property
    而没有相应的
    @synthesize
    指令将会为您生成一个实例变量来存储属性中的实际值。对于像
    foo
    这样的属性,默认生成的 ivar 将是
    _foo
  • 但是,您可以使用显式
    @synthesize
    指令为变量提供您自己的名称,并且当您这样做时,您可以使用您想要的任何名称访问 ivar:
    • 省略
      @synthesize
      指令相当于
      @synthesize foo=_foo;
      (即将
      foo
      属性映射到
      _foo
      ivar)
    • @synthesize foo;
      本身相当于
      @synthesize foo=foo;
      (即将
      foo
      属性映射到
      foo
      ivar)
    • @synthesize foo=bar;
      foo
      属性映射到
      bar
      ivar

恰好在 Objective-C 类中,ivars 可以直接通过它们的裸名访问 - 在你的 SomeObject

 类中,写 
foo
 指的是 ivar 本身,
not 指的是属性。

    在您的原始代码中,因为
  • foo
     属性实际上使用 
    foo
     ivar (因为您没有自己实现 
    foo
     方法),所以 
    foo
    self.foo
     恰好返回相同的值
  • 在更新后的代码中,您使用
  • foo
     指令显式合成 
    @synthesize
     ivar,但随后为 
    foo
     getter 提供您自己的实现,这就是您编写 
    self.foo
     时所调用的。因为 
    foo
     ivar 从未设置过,所以默认情况下它会获得 
    nil
换句话说,在引用属性时,你无法避免写

self.foo

,一般来说,建议你避免写 
@synthesize foo;
,以避免直接访问方法与直接访问 ivar 时可能发生的混淆。

© www.soinside.com 2019 - 2024. All rights reserved.