【问题标题】:Obj-C How to set a property on all elements of an array [duplicate]Obj-C如何在数组的所有元素上设置属性[重复]
【发布时间】:2016-08-06 21:25:28
【问题描述】:

我正在尝试做这样的事情:

[array makeObjectsPerformSelector:@selector(setFoo:) withObject:[NSNumber numberWithBool:YES]];

其中foo 是数组元素类的公共属性(类型BOOL)。但是,这不起作用,我认为这与我传递参数的方式有关,因为当我遍历数组并为数组的每个元素调用 [array[i] setFoo:YES] 时它工作正常。我也尝试过传递@YES@"YES"

【问题讨论】:

  • 方法setFoo: 采用BOOL 参数,但您提供的是NSNumber。你不能那样做。
  • 那么正确的方法是什么?

标签: objective-c


【解决方案1】:

这个:

@interface Blarg:NSObject
@property BOOL flag;
@end
@implementation Blarg
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray *a = @[[Blarg new], [Blarg new], [Blarg new]];
        NSLog(@"Start %@", [a valueForKey:@"flag"]);
        [a setValue:@YES forKey:@"flag"];
        NSLog(@"Yes %@", [a valueForKey:@"flag"]);
        [a setValue:@NO forKey:@"flag"];
        NSLog(@"No %@", [a valueForKey:@"flag"]);

    }
    return 0;
}

喷这个:

2016-04-14 23:28:00.648 dfjkdf[767:101069] Start (
    0,
    0,
    0
)
2016-04-14 23:28:00.650 dfjkdf[767:101069] Yes (
    1,
    1,
    1
)
2016-04-14 23:28:00.650 dfjkdf[767:101069] No (
    0,
    0,
    0
)

对吗?有点。一般来说,这不是你应该使用的模式。

你最好做这样的事情:

    [a enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        Blarg *b = obj;
        b.flag = YES;
    }];

或者,使用现代编译器会更好:

    [a enumerateObjectsUsingBlock:^(Blarg * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.flag = YES;
    }];

这是几行额外的代码,但它的类型是正确的,因此,如果将来代码更改以破坏它,编译器会尖叫。元编程阻碍了编译器帮助您的能力。

【讨论】:

  • 如果将obj 参数声明为Blarg 而不是id,则枚举会更简单。然后你只需做obj.flag = YES;
  • @rmaddy 谢谢!我总是忘记你现在可以做到这一点......当我们第一次创建 Blocks 时,编译器无法做到这一点。 :)
【解决方案2】:

使用键值编码:

[array setValue:@YES forKey:@"foo"];

来自docs for NSArray's override of -setValue:forKey:

使用指定的 valuekey 对数组的每个项调用 setValue:forKey:

【讨论】:

    猜你喜欢
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 2014-09-13
    • 1970-01-01
    • 2023-03-12
    • 2016-04-22
    • 2016-09-09
    相关资源
    最近更新 更多