objective-c - 修改 Objective-C block 中的参数

标签 objective-c objective-c-blocks

我想修改 Objective-C block 内部存在的各种变量。

我知道我可以使用 __block 直接访问和修改变量声明变量时的属性。所以这有效:

__block NSMutableString *alertMessage;

void(^appendMessage)(NSMutableString*, NSString*)= ^(NSString *append){

    if (!alertMessage)
    {
        alertMessage = [NSMutableString new];
    }

    if ([append length] > 0)
    {
        [alertMessage appendString:@"\n"];
    }

    [alertMessage appendString:append];
};

appendMessage(@"Alert part 1"); //This works fine

但是,我想创建一个可以对传递的变量执行操作的 block ,使我能够对 block 外部的多个变量使用该操作,而无需直接访问相同的变量。类似于以下内容:

__block NSMutableString *alertMessage;
__block NSMutableString *otherString;

void(^appendMessage)(NSMutableString*, NSString*)= ^(NSMutableString *string, NSString *append){

    if (!string)
    {
        string = [NSMutableString new];
    }

    if ([append length] > 0)
    {
        [string appendString:@"\n"];
    }

    [string appendString:append];
};

//The following do not work as intended
appendMessage(alertMessage, @"Alert Part 1"); 
appendMessage(otherString, @"Bleh bleh");     

我希望能够使用上面的 block 来修改之前声明的变量。

怎样才能实现这样的操作呢?这可能吗?

最佳答案

您的问题显示了对值和变量的一些混淆,也许以下内容会有所帮助。

Modify parameters in Objective-C blocks

在(Objective-)C 中,方法/函数/ block 的所有参数均通过传递,例如当调用f(x)时,变量x的值被传递给f,而不是变量本身。这称为按值调用

有些语言确实允许传递变量,称为按引用调用。使用时,参数必须是变量,并且函数内的参数名称实际上是所提供变量的别名。 (Objective-)C 不直接支持这一点。

但是您可以在(Objective-)C 中模拟它。它并不常用,但有一个值得注意的异常(exception):许多方法使用它来返回 NSError * 值。

您稍后评论:

What I want to achieve includes object creation, which is essentially what the question now boils down to. "Can I create an object declared outside within a block?". The answer which I have gathered with the help of all the activity here is NO.

可以,这只是一个是否应该(即设计是否正确?)以及最好的方法的问题。

解决特定问题的直接方法是编写一个函数:

NSMutableString *alertMessage;
NSMutableString *otherString;

NSMutableString *(^appendMessage)(NSMutableString *, NSString *) =
   ^(NSMutableString *string, NSString *append)
   {
      if (!string)
         string = [NSMutableString new];

      if (append.length > 0)
      {
         [string appendString:@"\n"];
         [string appendString:append];
      }

      return string;
   };

alertMessage = appendMessage(alertMessage, @"Alert Part 1");
otherString = appendMessage(otherString, @"Bleh bleh");

如果您真的(真的,真的)想要,您可以通过传递其地址来“传递变量”(使用& 运算符)和 block 内的间接(使用 * 运算符)来获取/设置值:

void (^appendMessage)(NSMutableString **, NSString *) =
   ^(NSMutableString **stringPtr, NSString *append)
   {
      if (!stringPtr) return; // no "variable" passed

      NSMutableString *string = *stringPtr; // use indirection to get the value in the passed variable

      if (!string)
         string = [NSMutableString new];

      if (append.length > 0)
      {
         [string appendString:@"\n"];
         [string appendString:append];
      }

      *stringPtr = string; // use indirection to set the passed variable
   };


appendMessage(&alertMessage, @"Alert Part 1"); // pass "variable" by passing its address
appendMessage(&otherString, @"Bleh bleh");

虽然上面的代码是有效的代码,但对于像您这样的简单情况,通常不建议使用 Objective-C 进行编码实践。

Once you take the address of a variable you need to be concerned over the lifetime of that variable - if you attempt to use the address to access the variable after the variable has been destroyed your program will fail (the dangling pointer problem)

__block怎么样?

以上示例均未在任何地方使用 __block

当 block 默认引用变量时,它会捕获创建 block 时的变量__block 属性将其更改为捕获变量(因此它的值可以通过 block 更改)并更改捕获变量的生命周期,如果必需的(因此变量的生存时间至少与捕获 block 一样长,从而避免了悬空指针问题)。

__block 属性不适用于您的情况,因为您希望根据调用捕获不同变量。

HTH

关于objective-c - 修改 Objective-C block 中的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36398504/

相关文章:

objective-c - -[NSNotificationCenter postNotificationName :object:] Can I pass nil for object?

objective-c - 我们是否必须保留非 ARC 中方法返回的对象?

ios - 如何使用 __block 和完成 block 避免内存泄漏

objective-c - 如何在 Objective-C/iOS 中可靠地对命令进行排序

iphone - 如何将数据转换为mp4格式

ios - 如何使用滚动动画关注 UITableview 中的最后一个单元格?

ios - 如果更改了呈现 View Controller ,如何关闭模态视图 Controller ?

objective-c - 枚举 ALAssetsLibrary

ios - 在ARC中保留局部变量的对象引用

ios - 有人可以为我澄清这个 block 吗?