我想修改 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/