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

时间:2014-08-11 16:34:28

标签: ios objective-c

所以我有一个实例函数,它接受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. } 的值而不是引用它。我该怎么办?有没有办法让新变量引用我传递给函数的变量?谢谢!


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

{{1}}

2 个答案:

答案 0 :(得分:1)

你必须给一个块一些引用变量来修改。通过调用doThis:,你可以按值(而不是通过引用)传递一个整数,因此失败块只能有效地获得integer值的副本 - 因此原始变量没有机会被修改。

同样适用于__block NSInteger temp = integer - temp获取integer的副本。阻止可以修改temp,但它只是integer的副本 - 因此没有机会更改原始值。

要更改值,请使用:

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

这样您就可以通过self获得对输入的引用。但是,它在ARC环境中被认为是错误的,因为self被块隐含地捕获,这可能导致保留周期。因此,最好的方法是创建对自我的弱引用,并让它被块捕获:

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

P.S。你的问题有效地揭示了,你不知道,它是如何工作的 - 指针,通过值/参考传递参数,ObjC块等。你应该获得更多关于你的编程语言的理论知识,以避免将来出现这样的问题。

答案 1 :(得分:0)

与C一样,Objective-C按值传递所有内容。它通过将对象放在堆上并通过指针引用它们来焊接C顶部的对象。所以你传递的东西不是对象本身,它是对象的地址。地址本身按值传递。但如果有人知道地址,他们就可以进入堆并修改对象。

您对doThis:的输入是参数integer。因此,在调用该方法时会发生什么:

  1. 无论你写的参数应该在哪里进行评估,如有必要,都会隐式转换为`NSInteger';
  2. 将向该方法提供NSInteger的副本;
  3. 收到了自己的副本后,integer现在等同于该方法的局部变量。
  4. 所以,例如你可以这样做:

    [object doThis:8];
    

    8被复制到doThis:中有效的局部变量中,因此您可以修改integer所有您喜欢的内容,无论您传入的是常量。

    如果您希望doThis:能够修改整数,那么您需要提供指向它的指针。一旦你有了,你应该没有问题在块内使用该指针。指针本身将被捕获,但是,当将指针传递给方法时,如果您修改指针所指向的内容,则会影响到那里的所有其他人。