0

假设我有一个具有 2 个属性的类:

@interface MyClass ()

@property (strong, nonatomic) NSString *strA;
@property (strong, nonatomic) NSString *strB;

@end

在那个类的某个地方,我有一个方法应该为这些属性之一赋值。问题是 - 该属性将在运行时确定。我该怎么做呢?我想在没有代码复制的情况下做到这一点(可能是一个非常复杂的方法)。例如,这很糟糕:

- (void) mutateProperty:(BOOL)assignToA
{
   if (assignToA)
   {
       self.strA = @"newStr";
   }
   else
   {
       self.strB = @"newStr";
   }
}

我希望能够完成类似的事情:

- (void) mutateProperty:(BOOL)assignToA
{
   NSString *propertyToUse = nil;
   if (assignToA)
   {
       propertyToUse = self.strA;
   }
   else
   {
       propertyToUse = self.strB;
   }

   propertyToUse = @"newStr" //But this will only change the propertyToUse variable's value and not affect the scope outside the method.
}
4

1 回答 1

2

发布的代码不是作业,而是发送给自己的消息:

self.strA = @"newStr";

真的是

[self setStrA:@"newStr"];

(如果您为属性声明了自定义设置器,方法名称可能会有所不同。)

所以你的问题是关于调度方法。有很多方法可以做到这一点,但在细节上都有所不同。然而,对于您的情况,在代码中有一个点,您只能在两个选项中进行选择,我会使用您已经发布的普通条件。它的可读性最高,代码重复最少。

如果您的案例比您发布的代码更复杂,您可能希望使用一些不同的调度方式。

在 Objective-C 中调度最基本的方法是手动计算选择器:

SEL selector = NULL;
switch (status) {
    case 1:
        selector = @selector(setStrA:);
        break;
    case 2:
        selector = @selector(setStrB:);
        break;
    case 3:
        selector = @selector(setStrC:);
        break;
}
[self performSelector:selector withObject:@"newStr"];

这与 ARC 不能很好地配合,因为 ARC 不能使用选择器的名称来确定参数和返回类型所有权。您必须使编译器警告静音,这很难看。

正如 nielsbot 所指出的,设置任意属性的内置方法是 KVC:您可以计算 KVC 用来查找匹配方法的“密钥”:

NSString *key = nil;
switch (status) {
    case 1:
        key = @"strA";
        break;
    case 2:
        key = @"strB";
        break;
    case 3:
        key = @"strC";
        break;
}
[self setValue:@"newStr" forKey:key];

这有点开销,但它也适用于 POD 参数类型。

于 2013-09-09T08:45:19.020 回答