关于Objective-C头文件中的property为readonly,外部还能set成功

发布时间 2023-08-06 16:44:09作者: 夏风已过

起初是同事和我说,property为readonly,外部还能set成功。实在没想明白。

常规的写法, .m中可以直接set成功,而外部创建的FCTest对象,无法set成功(见FCObject)。

FCTest.h

@interface FCTest : NSObject

@property (nonatomic, copy, readonly) NSString *name;

@end

FCTest.m

@interface FCTest ()

@property (nonatomic, copy) NSString *name;

@end

@implementation FCTest

+ (void)test {
    FCTest *test = [[FCTest alloc] init];
    test.name = @"hahaha"; // 不会编译失败
}

@end

FCObject.m

+ (void)test {
    FCTest *test = [[FCTest alloc] init];
    test.name = @"hahaha"; // 编译报错
}

那是什么原因导致set成功了呢?

我们先排除kvc,其次.m,甚至分类都没有调用set方法。那就只剩下协议了。

我们先试下在协议添加readonly的property的set方法。

@protocol FCTestProtocol <NSObject>

- (void)setName:(NSString *)name;

@end

@interface FCTest : NSObject <FCTestProtocol>

加载协议之后,FCObject中编译通过了。

最后查了工程的代码,确实是有一个协议中有set方法。

oc和swift混编时,在swift中调用FCTest,可以很明显的看出来问题。

let test = FCTest()
test.name = "hahaha" // 编译报错
test.setName("hahaha")

可以看到,name不能直接等于,只能通过set方法。

总结:不知道property为readonly的情况,为什么在协议中还添加了set方法,但总算找到了原因。