Ios 使用块的返回值动态创建字符串
因此,我试图动态地构建一个字符串,我真的希望构建这个字符串的所有代码都存在于作为参数传递给Ios 使用块的返回值动态创建字符串,ios,objective-c,string,objective-c-blocks,Ios,Objective C,String,Objective C Blocks,因此,我试图动态地构建一个字符串,我真的希望构建这个字符串的所有代码都存在于作为参数传递给stringWithFormat方法的块中。以下代码示例应演示我试图实现的目标: NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", ^NSString*(void){ NSString *language = [[NSLocale preferredLanguages] ob
stringWithFormat
方法的块中。以下代码示例应演示我试图实现的目标:
NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", ^NSString*(void){
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString *locale = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
return [NSString stringWithFormat:@"%@_%@", language, locale];
}];
这项工作的预期产出将类似于
Device Language: en_GB
然而,我从这个方法得到的输出实际上返回了NSGlobalBlock方法的描述
,例如
Device Language: <__NSGlobalBlock__:0x30a35c>
设备语言:
这是因为我没有在字符串中使用正确的占位符,还是没有声明块返回一个
NSString
对象?这是一个好问题
问题出在stringWithFormat:
中。在处理其格式字符串时,当它到达%@
时,它会找到对象参数,对其调用-description
,并将对象的描述添加到其输出中。本例中的描述为
您可以通过以下操作来解决此问题:
NSString*(^userLanguage)(void) = ^(void) {
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale displayNameForKey:NSLocaleIdentifier
value:[locale localeIdentifier]];
return [NSString stringWithFormat:@"%@_%@", language, locale];
};
NSString *language = userLanguage();
NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", language];
当然,你现在不需要块,所以你可以这样做:
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale displayNameForKey:NSLocaleIdentifier
value:[locale localeIdentifier]];
NSString *userLanguage = [NSString stringWithFormat:@"%@_%@", language, locale];;
NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", userLanguage];
这是因为您将块本身作为参数传递给
stringWithFormat:
,
而不是调用块的结果:
NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", ^NSString*(void){
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale displayNameForKey:NSLocaleIdentifier
value:[locale localeIdentifier]];
return [NSString stringWithFormat:@"%@_%@", language, locale];
}()];
请注意,使用
而不是块:
NSString * deviceLanguage = [NSString stringWithFormat:@"Device Language: %@", ({
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale displayNameForKey:NSLocaleIdentifier
value:[locale localeIdentifier]];
[NSString stringWithFormat:@"%@_%@", language, locale];
})];
因为要将块对象传递给
stringWithFormat
:所以要打印描述。就像@MartinR的回答一样。
如果你像这样重新编码,你的代码块会更容易管理
// first you declare a block like this, to retain it or pass it multiple times
typedef NSString* (^MyBlock)(void);
MyBlock block = ^{
NSLocale *locale = [NSLocale currentLocale];
NSString *language = [locale displayNameForKey:NSLocaleIdentifier
value:[locale localeIdentifier]];
// print the local id
return [NSString stringWithFormat:@"%@_%@", language, locale.localeIdentifier];
};
// Now pass it to stringWithFormat:
NSString *deviceLanguage = [NSString stringWithFormat:@"device language: %@", block()];
感谢您的回答,这很有意义,但是我试图将所有内容都保存在一条语句中,以获得干净的代码,因此我将接受Martin的回答,但这同样有效。你对它失败的确切原因的解释非常有用。但愿我能接受这两个答案<代码>对于干净的代码是有争议的:P在大多数情况下,我更喜欢方法调用而不是复合语句。你可能是对的,我只是喜欢这样一种想法,即在创建字符串的方法中(实际上)可以看到字符串构造的所有内容,但我只是在尝试块。谢谢,这正是我想要的。我以前从未遇到过复合语句表达式,这看起来非常有用!在第一种情况下,只需写入[NSString stringWithFormat:@“设备语言:%@,^{…}()];这让我感觉好多了,我错过的只是实际执行块的最后一个()!谢谢,我忘了你应该
typedef
像这样的重要块。@Sammio2,也请看我打印的是locale.localeIdentifier,而不是locale,以获得所需的结果。我确实注意到了,谢谢。此后,我意识到,我所寻找的实际信息可以通过以下简单的代码获得:[[NSLocale preferredLanguages]objectAtIndex:0]
使整个问题无效,但它教会了我一些关于块的知识!