NSMutableString和NSString的类别导致绑定混乱? [英] Categories for NSMutableString and NSString causing binding confusion?

查看:261
本文介绍了NSMutableString和NSString的类别导致绑定混乱?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经扩展了NSString和NSMutableString与一些方便的方法使用类别。这些添加的方法具有相同的名称,但具有不同的实现。例如,我已经实现rubystrip函数,删除端点的空格字符,但对于NSString它返回一个新的字符串,对于NSMutableString它使用deleteCharactersInRange剥离现有的字符串并返回它(像红宝石条!)。

I have extended both NSString and NSMutableString with some convenience methods using categories. These added methods have the same name, but have different implementations. For e.g., I have implemented the ruby "strip" function that removes space characters at the endpoints for both but for NSString it returns a new string, and for NSMutableString it uses the "deleteCharactersInRange" to strip the existing string and return it (like the ruby strip!).

以下是典型的标题:

@interface NSString (Extensions)
-(NSString *)strip;
@end

@interface NSMutableString (Extensions)
-(void)strip;
@end


$ b < ],它试图运行NSMutableString版本并引发一个扩展。

The problem is that when I declare NSString *s and run [s strip], it tries to run the NSMutableString version and raises an extension.

NSString *s = @"   This is a simple string    ";
NSLog([s strip]);

失败:


由于未捕获而终止应用程序
exception
'NSInvalidArgumentException',reason:
'尝试使用deleteCharactersInRange:'

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with deleteCharactersInRange:'


推荐答案

你被一个实现细节咬了:一些NSString对象是NSMutableString的子类的实例,

You've been bitten by an implementation detail: Some NSString objects are instances of a subclass of NSMutableString, with only a private flag controlling whether the object is mutable or not.

这是一个测试应用程式:

Here's a test app:

#import <Foundation/Foundation.h>

int main(int argc, char **argv) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString *str = [NSString stringWithUTF8String:"Test string"];
    NSLog(@"%@ is a kind of NSMutableString? %@", [str class], [str isKindOfClass:[NSMutableString class]] ? @"YES" : @"NO");

    [pool drain];
    return EXIT_SUCCESS;
}

如果你至少编译并运行Leopard得到这个输出:

If you compile and run this on Leopard (at least), you'll get this output:

NSCFString is a kind of NSMutableString? YES

正如我所说,对象有一个私人标志控制是否可变。因为我经历了NSString而不是NSMutableString,这个对象是不可变的。如果你尝试改变它,像这样:

As I said, the object has a private flag controlling whether it's mutable or not. Since I went through NSString and not NSMutableString, this object is not mutable. If you try to mutate it, like this:

NSMutableString *mstr = str;
[mstr appendString:@" is mutable!"];

你会得到一个当之无愧的警告但这是一个坏主意)和(2)在你自己的应用程序中有相同的异常。

you'll get (1) a well-deserved warning (which one could silence with a cast, but that would be a bad idea) and (2) the same exception you got in your own application.

我建议的解决方案是将你的变形条包裹在 @try 阻止,并在 return [super strip] ) > @catch 阻止。

The solution I suggest is to wrap your mutating strip in a @try block, and call up to your NSString implementation (return [super strip]) in the @catch block.

此外,我不建议给方法不同的返回类型。我将使变化的一个返回 self ,如 retain autorelease do。然后,你总是可以这样做:

Also, I wouldn't recommend giving the method different return types. I would make the mutating one return self, like retain and autorelease do. Then, you can always do this:

NSString *unstripped = …;
NSString *stripped = [unstripped strip];

而不必担心 untripted 是否是可变字符串或不。实际上,此示例提供了一个很好的例子,您应该完全删除变异的 strip ,或者将复制 strip 重命名为 stringByStripping 或某事(类似于 replaceOccurrencesOfString:... stringByReplacingOccurrencesOfString:... )。

without worrying about whether unstripped is a mutable string or not. In fact, this example makes a good case that you should remove the mutating strip entirely, or rename the copying strip to stringByStripping or something (by analogy with replaceOccurrencesOfString:… and stringByReplacingOccurrencesOfString:…).

这篇关于NSMutableString和NSString的类别导致绑定混乱?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆