当前位置:  开发笔记 > IOS > 正文

如何从像@"xxx =%@,yyy =%@"和NSArray对象这样的格式字符串创建NSString?

如何解决《如何从像@"xxx=%@,yyy=%@"和NSArray对象这样的格式字符串创建NSString?》经验,为你挑选了3个好方法。

有没有办法从像@"xxx =%@,yyy =%@"和NSArray对象这样的格式字符串创建一个新的NSString?

在NSSTring类中有许多方法,如:

- (id)initWithFormat:(NSString *)format arguments:(va_list)argList
- (id)initWithFormat:(NSString *)format locale:(id)locale arguments:(va_list)argList
+ (id)stringWithFormat:(NSString *)format, ...

但是没有它们将NSArray作为参数,我找不到从NSArray创建va_list的方法......



1> Peter N Lewi..:

实际上从NSArray创建一个va_list并不困难.请参阅Matt Gallagher 关于此主题的优秀文章.

这是一个NSString类别,可以执行您想要的操作:

@interface NSString (NSArrayFormatExtension)

+ (id)stringWithFormat:(NSString *)format array:(NSArray*) arguments;

@end

@implementation NSString (NSArrayFormatExtension)

+ (id)stringWithFormat:(NSString *)format array:(NSArray*) arguments
{
    char *argList = (char *)malloc(sizeof(NSString *) * arguments.count);
    [arguments getObjects:(id *)argList];
    NSString* result = [[[NSString alloc] initWithFormat:format arguments:argList] autorelease];
    free(argList);
    return result;
}

@end

然后:

NSString* s = [NSString stringWithFormat:@"xxx=%@, yyy=%@" array:@[@"XXX", @"YYY"]];
NSLog( @"%@", s );

不幸的是,对于64位,va_list格式已经改变,因此上面的代码不再有效.并且可能不应该被使用,因为它取决于明显可能改变的格式.鉴于没有真正强大的方法来创建va_list,更好的解决方案是简单地将参数数量限制为合理的最大值(比如10),然后使用前10个参数调用stringWithFormat,如下所示:

+ (id)stringWithFormat:(NSString *)format array:(NSArray*) arguments
{
    if ( arguments.count > 10 ) {
        @throw [NSException exceptionWithName:NSRangeException reason:@"Maximum of 10 arguments allowed" userInfo:@{@"collection": arguments}];
    }
    NSArray* a = [arguments arrayByAddingObjectsFromArray:@[@"X",@"X",@"X",@"X",@"X",@"X",@"X",@"X",@"X",@"X"]];
    return [NSString stringWithFormat:format, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9] ];
}


遗憾的是,这在64位模拟器中失败了.
想知道如何在iOS 5.0中执行此操作,它不允许`[arguments getObjects:(id*)argList];`并吐出`指向非const类型'id'的指针,没有明确的所有权
为那些想知道如何使用ARC的人提供了答案:http://stackoverflow.com/a/13499735/881197

2> SolidSun..:

基于此答案使用自动参考计数(ARC):https://stackoverflow.com/a/8217755/881197

NSString使用以下方法添加类别:

+ (id)stringWithFormat:(NSString *)format array:(NSArray *)arguments
{
    NSRange range = NSMakeRange(0, [arguments count]);
    NSMutableData *data = [NSMutableData dataWithLength:sizeof(id) * [arguments count]];
    [arguments getObjects:(__unsafe_unretained id *)data.mutableBytes range:range];
    NSString *result = [[NSString alloc] initWithFormat:format arguments:data.mutableBytes];
    return result;
}


第一行末尾出现一个狂野分号.小心的人!

3> Panagiotis K..:

我想到的一个解决方案是,我可以创建一个适用于固定大量参数的方法,例如:

+ (NSString *) stringWithFormat: (NSString *) format arguments: (NSArray *) arguments {
    return [NSString stringWithFormat: format ,
          (arguments.count>0) ? [arguments objectAtIndex: 0]: nil,
          (arguments.count>1) ? [arguments objectAtIndex: 1]: nil,
          (arguments.count>2) ? [arguments objectAtIndex: 2]: nil,
          ...
          (arguments.count>20) ? [arguments objectAtIndex: 20]: nil];
}

我还可以添加一个检查,以查看格式字符串是否包含超过21'%'的字符,并在这种情况下抛出异常.


实际上,我将此视为最佳解决方案.非常实用且保证可移植(虽然va_list的内容不太可能改变,所以它也是一个非常安全的赌注).手动输入20个参数没有任何问题(如果你真的想要,你可以使用脚本或Vim/Emacs /任何宏自动化它).
推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有