【问题标题】:Cocoa - Calling a variadic method from another variadic one (NSString stringWithFormat call)Cocoa - 从另一个可变参数调用一个可变参数方法(NSString stringWithFormat 调用)
【发布时间】:2011-01-15 23:52:52
【问题描述】:

[NSString strigWithFormat:format] 有问题,因为它返回一个 id,而且我有很多代码将 NSString var 更改为其他个人类型。但是编译器并没有阻止我在某些地方将 NSString 设置为另一种类型的对象。

所以我正在编写一个 NSString 类别,我打算将所有对 stringWithFormat 的调用替换为 myStringWithFormat

代码是:

@interface NSString (NSStringPerso)
+ (NSString*) myStringWithFormat:(NSString *)format;
@end



@implementation NSString (NSStringPerso)
+ (NSString*) myStringWithFormat:(NSString *)format {
    return (NSString*)[NSString stringWithFormat:format];
}
@end

编译器告诉我“Format not a string literal and no format arguments”。

你有什么办法可以使这项工作发挥作用吗?

【问题讨论】:

    标签: cocoa nsstring compiler-warnings categories variadic


    【解决方案1】:

    NSString 包含一个从可变参数函数中获取参数列表的方法。看看这个示例函数:

    void print (NSString *format, ...) {
        va_list arguments;
        va_start(arguments, format);
    
        NSString *outout = [[NSString alloc] initWithFormat:format arguments:arguments];
        fputs([output UTF8String], stdout);
        [output release];
    
        va_end(arguments);
    }
    

    其中一些代码无关紧要,但关键行是NSString *output = [[NSString alloc] initWithformat:format arguments:arguments];。这就是您可以在可变参数函数/方法中构造NSString 的方式。


    在您的情况下,您的代码应如下所示:

    + (NSString *)myStringWithFormat:(NSString *)format, ... {
        va_list arguments;
        va_start(arguments, format);
    
        NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arguments];
        va_end(arguments);
    
        // perform some modifications to formattedString
    
        return [formattedString autorelease];
    }
    

    【讨论】:

      【解决方案2】:

      这里没有 Objective-C 专家,但 stringWithFormat 的原始方法签名包含省略号,它允许您以 argument 的格式传入将替换为占位符的参数。

      编辑:stringWithFormat 是一种所谓的 variadic 方法。这是一个link 的示例。

      【讨论】:

      • @sm :很好,但是我如何从另一个调用可变参数方法?我无法推断显示的示例来执行此操作...
      • 看起来,呃,你不能,因为 stringWithFormat 没有使用 va_list 的替代版本。尝试包装 initWithFormat ,它有一个。另外,看看这个:stackoverflow.com/questions/150543/…
      • 这不是真的。 NSString 确实有一个使用 va_list 的版本:initWithFormat:arguments:。看看NSString Class Reference
      • @itaiferber 你是对的,不知何故我没有注意到。为您的回答 +1。
      【解决方案3】:

      感谢您的帮助。 阅读您的参考文档,我找到了解决方案!

      这行得通:

      在.h

      @interface NSString (NSStringPerso)
      + (NSString*) strWithFormatPerso:(id)firstObject, ...;
      @end
      

      在.m中

      @implementation NSString (NSStringPerso)
      + (NSString*) strWithFormatPerso:(id)firstObject, ... {
      
          NSString* a;
      
          va_list vl;
          va_start(vl, firstObject);
          a = [[[NSString alloc] initWithFormat:firstObject, vl] autorelease];
          va_end(vl);
      
          return a;
      }
      @end
      

      【讨论】:

      • Cocoa 的两条规则是“不要向已创建但未初始化的对象发送消息”和“不要两次初始化对象”。避免这两种情况的最简单方法是永远不要与初始化分开分配对象。您应该在同一个消息表达式中分配和初始化 NSString 对象。我也会将自动释放器移到那里,并在同一行中完成所有三个操作。您可以将a 的声明移动到va_startva_end 之间,或者将其保留在原处并将其初始化程序拆分为一个赋值;这取决于你的个人风格。
      • @Peter Hosey:我已经编辑了我的答案。这是你想的代码吗?
      猜你喜欢
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多