繁体   English   中英

在Objective-C块中修改全局变量

[英]Modifying global variables in Objective-C blocks

所以我有一个实例函数,它以NSInteger作为参数; 在函数中,我有一个方块。 我需要修改传递给函数的NSInteger 但这不是__block类型。 我应该怎么做呢? 原始功能太复杂了,所以我在这里放一个简化的版本...

//@interface
@property(nonatomic) NSInteger input; 
...

//@implementation
[self doThis:self.input];

-(void)doThis:(NSInteger)integer{
    [API doSomethingWithThisInteger:integer success:^(NSMutableDictionary *data){
        ...
    } failure:^(NSString *error){
        integer--;
    }
}

我知道我应该传递一个__block类型的变量,但是如果我在函数中初始化了一个新变量(即__block NSInteger temp = integer ),并将temp--而不是integer-- )放入failure块,然后是self.input将保持不变,因为初始化语句复制input的值而不是引用它。 我应该在这里做什么? 有没有办法使新变量成为我传递给函数的变量的引用? 谢谢!


编辑:解决问题的方法-使用全局变量而不是属性-

@implementation
NSInteger input;
....
[self doThis:&input]; //sends in the address of the input
....
- (void)doThis:(NSInteger *)integer{ //takes the pointer of the input instead of its actual value so it gets referenced rather than getting copied
    [API doSomethingWithThisInteger:integer success:^(NSMutableDictionary *data){
    ...
} failure:^(NSString *error){
    *integer = *integer - 1; //dereference the pointer to get the value.
}

您必须为块提供一些对变量的引用以进行修改。 通过调用doThis:doThis:值传递整数(而不是按引用传递),因此故障块实际上只能获得integer数值的副本-因此原始变量没有机会被修改。

这同样适用于__block NSInteger temp = integer -温度得到一个副本integer Block可以修改temp ,但是它只是integer的副本-因此没有机会更改原始值。

要更改值,请使用:

-(void)doThis
{
    [API doSomethingWithSuccess:^(NSMutableDictionary *data)
    {
        ...
    } 
    failure:^(NSString *error)
    {
        self.input--;
    }
}

这样,您可以通过self获得对输入的引用。 但是,在ARC环境中,这被认为是不好的,因为self会被块隐式捕获,这可能会导致保留周期。 因此,最好的方法是创建对self的弱引用,并使其被块捕获:

-(void)doThis
{
    __weak typeof(self) weakSelf = self;
    [API doSomethingWithSuccess:^(NSMutableDictionary *data)
    {
        ...
    } 
    failure:^(NSString *error)
    {
        weakSelf.input--;
    }
}

PS您的问题有效地揭示了您不知道它是如何工作的-指针,按值/按引用传递参数,ObjC块等。您应该获得有关编程语言的更多理论知识,以避免将来出现此类问题。

与C一样,Objective-C也会按值传递所有内容。 通过将对象放在堆上并通过指针引用它们,将对象焊接在C之上。 因此,您所传递的不是对象本身,而是对象的地址。 地址本身按值传递。 但是,如果有人知道地址,他们可以去堆并修改对象。

您对doThis:输入是一个参数integer 因此,当调用该方法时,将会发生:

  1. 无论您在何处编写了参数,都将对其进行评估,并在必要时将其隐式转换为NSInteger;
  2. NSInteger的副本将提供给该方法;
  3. 收到自己的副本后, integer现在等效于该方法的局部变量。

因此,例如,您可以这样做:

[object doThis:8];

8复制到doThis:有效的局部变量中,因此您可以随意修改integer而不管传入常量的事实如何。

如果您希望doThis:能够修改整数,则需要提供一个指向它的指针。 并且一旦有了,您就可以在块内使用该指针了。 指针本身将被捕获,但是,就像在将指针传递给方法时一样,如果您修改了指针指向的内容,那么将影响到那里的所有人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM