在 Objective-C 中,如何设置属性的属性,即设置为另一个类属性的类?

Posted

技术标签:

【中文标题】在 Objective-C 中,如何设置属性的属性,即设置为另一个类属性的类?【英文标题】:In Objective-C, how do you set up properties of properties, i.e. of a class set up as another class property? 【发布时间】:2010-07-24 15:03:48 【问题描述】:

我一直在尝试设置一个类的实例属性,该类本身就是一个包含实例变量的类。我想将这些作为属性访问。在 C# 中,使用预先设置的 get 和 set 变量很容易做到这一点:

public class TheOverallClass

    private ClassName _propertyName;
    public ClassName PropertyName
    
        get  return _propertyName; 
        set  _propertyName = value; 
    

...和 ​​PropertyName 在构造函数中被实例化:

    public TheOverallClass()
    
        PropertyName = new ClassName();
    

假设 PropertyName 有一个名为 ThisValue 的实例变量/属性,我可以通过以下方式访问它:

TheOverallClass overallClass = new TheOverallClass();
overallClass.PropertyName.ThisValue = 20;    // int
Console.WriteLine(overallClass.PropertyName.ThisValue.ToString());

我将如何在 Objective-C 中执行此操作?我尝试过,但遇到了困难。

PropertyName 等价物编码为:

...在另一个类.h中:

@interface AnotherClass : NSObject 
    int thisValue;

@property (readwrite,assign) int ThisValue;
@end

...在另一个类.m

@implementation AnotherClass
@synthesize ThisValue=thisValue;
@end

然后在 ClassName 等价物 MyClass 中使用它:

...在 MyClass.h 中:

@class AnotherClass;
@interface MyClass : NSObject 
    AnotherClass* another;

@property (nonatomic,retain) AnotherClass* Another;
@end

...在 MyClass.m 中:

@implementation MyClass
@synthesize Another=another;
@end

当我尝试在代码中获取/设置值时,Xcode 会返回“访问属性的未知 'ThisValue' 组件”。我用来访问的代码是:

MyClass* me = [[MyClass alloc] init];
me.Another.ThisValue = 20;
NSLog(@"Value = %i", me.Another.ThisValue);

我做错了什么?

【问题讨论】:

只是一个注释,但您应该遵守编码约定,即使属性以 lower 字母开头。 检查 MyClass.m 是否包含 AnotherClass.h。 【参考方案1】:

假设访问该属性的代码在 main.m 中,正如之前提到的,您需要为声明该属性的类(在本例中为 AnotherClass.h)添加一个导入语句。但是您的代码仍然无法按您期望的方式工作,因为它永远不会创建 AnotherClass 的嵌套实例。试试这个:

MyClass* me = [[MyClass alloc] init];
me.Another = [[AnotherClass alloc] init];
me.Another.ThisValue = 20;
NSLog(@"Value = %i", me.Another.ThisValue);

然后帮自己一个忙,不要更改 @synthesize 语句中的属性名称。而不是这样做......

@synthesize ThisValue=thisValue;

...就这样做...

@synthesize thisValue;

...然后像这样重写main中的代码...

MyClass* me = [[MyClass alloc] init];
me.another = [[AnotherClass alloc] init];
me.another.thisValue = 20;
NSLog(@"Value = %i", me.another.thisValue);

【讨论】:

谢谢 - 这是它倒下的地方!添加了 [[AnotherClass alloc] init] 并且代码完全可以运行!我还尝试并设法覆盖了 init 方法并在其中分配和初始化了 AnotherClass。【参考方案2】:

您是否在包含me.Another.ThisValue = 20; 的文件中包含AnotherClass.h?如果没有,它将不知道如何处理Another 类。

(此外,大写首字母通常保留给常量和类名,这与 C# 中的情况相反。)

【讨论】:

【参考方案3】:

您的代码应该可以工作:

// main.m


#import <Foundation/Foundation.h>

@interface AnotherClass : NSObject 
    int thisValue;

@property (readwrite,assign) int ThisValue;
@end

@implementation AnotherClass
@synthesize ThisValue=thisValue;
@end

@interface MyClass : NSObject 
    AnotherClass* another;

@property (nonatomic,retain) AnotherClass* Another;
@end

@implementation MyClass
@synthesize Another=another;
@end


int main (int argc, const char * argv[]) 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...

    MyClass* me = [[MyClass alloc] init];
    me.Another.ThisValue = 20;
    NSLog(@"Value = %i", me.Another.ThisValue);


    [pool drain];
    return 0;

抛开编码约定不谈,这段代码编译和运行都很好。

【讨论】:

代码编译运行,但是没有出现NSLog中的值。但是,我似乎没有分配或初始化 AnotherClass 实例。【参考方案4】:

我也有 .NET 背景,我明白你在做什么。

我想你也可以试试这个(以获得更多 C# 风格的行为):

.h 文件

@class AnotherClass;
@interface MyClass : NSObject 
    AnotherClass* another;

@property (nonatomic,retain) AnotherClass* Another;
@end

.m 文件

@implementation MyClass
@synthesize Another=another;

// Implementing a custom accessor
- (AnotherClass *)Another

    if (!another) 
        AnotherClass *other = [[AnotherClass alloc] init];
        another = other;
    
    return another;

@end

这样,无论您是否自己创建了该属性,都可以确保创建该属性。然后,您可以在AnotherClassinit 方法中实现一个默认值。

我知道这违反了 Objective-C 编码模式,但这是让它“工作”的一种方式。 :)

【讨论】:

以上是关于在 Objective-C 中,如何设置属性的属性,即设置为另一个类属性的类?的主要内容,如果未能解决你的问题,请参考以下文章

IOS/objective-c/core-data:如何从相关实体获取属性

Objective-C:(私有/公共属性)为外部类调用设置只读属性,为自调用设置只读属性

Objective-C 中的弱属性和强属性设置器属性

来自另一个类的 Objective-C 设置属性返回 Null

如何在 Swift 中覆盖 Objective-C 的只读属性?

如何在 Swift 中覆盖 Objective-C 的只读属性?