iOS中怎么判断可变和不可变的坑(更正版)

iOS中怎么判断可变和不可变的坑

  怎么判断NSStringNSMutableString

  看题

    BOOL result = [@"123" isKindOfClass:[NSMutableString class]];
    // A:YES     B:NO

  送分题一看就选B的。然而正确答案却是A(这里提及下涉及的两个概念:类簇,工厂模式)

  看控制台弄出来的结果

    id str0 = [NSString alloc];//NSPlaceholderString->NSString
    id str1 = [[NSString alloc] init];//__NSCFConstantString->__NSCFString->NSMutableString->NSString
    id str3 = [NSString stringWithFormat:@"123"];//NSTaggedPointerString->NSString
    id str4 = [NSMutableString alloc];//NSPlaceholderMutableString->NSMutableString->NSString
    id str5 = [NSMutableString new];//__NSCFString->NSMutableString->NSString

  字符串常量,也就是str1那种创建方式得到的类型是__NSCFConstantString并且明目张胆的是NSMutableString的子类。无论如何请勇敢的质疑苹果脑残的设计。并且后面的Array和Dictionary就不存在这种脑残的地方。我们无法知道到底黑盒子里有多少这种子类,根据倒推法:

  所以现在判断一个字符串是可变的这么写就行了

BOOL isMutable = [str isMemberOfClass:NSClassFromString(@"__NSCFString")];//请注意是isMemberOfClass:这个方法不要用成isKindOfClass:

 

  把Array的控制台结果也弄出来简单的看一下

    NSArray* arr0 =        [[NSArray alloc] init];//__NSArray0->NSArray
    NSArray* arr1 =        [NSArray arrayWithObject:@"123"];//__NSArrayI->NSArray
    NSMutableArray* arr3 =   [[NSMutableArray alloc] init];//__NSArrayM->NSMutableArray->NSArray

  可以发现虽然NSArray也子嗣众多,但不会出现String那种近亲乱的情况。

  判断Array是不可变的这么写就行了,不需要写字符串的类型

BOOL notMutable = [arr isKindOfClass:[NSArray class]]&&![arr isKindOfClass:[NSMutableArray class]];

  NSDictionary的情况同NSArray。

  转注出:原文

 

===========更正===========================

上面的方法在实际使用中被证明是错的,看如下两个方法

//在有的版本中执行结果如下
@(123).description;//__NSCFString->NSMutableString->NSString [NSString stringWithFormat:@"123%d",123]//__NSCFString->NSMutableString->NSString

就是说这两种情况从外部审查类型来看,根本和[NSMutableString new]的效果是一样的,而且是响应下面的方法的

[xxx respondsToSelector:@selector(appendFormat:)];

但是实际的情况是一调用就崩溃了。不听老人言吃亏在眼前,真的是最打脸的道理最朴素。一个不开源的东西,我们就是喜欢在外面赌博。

思考了很久我发现了解决之道,大道果然至简:我不知道它怎么实现的,但是苹果知道……

所以:

    id copyed = [xxx copy];
    if(copyed == xxx){
        @"不可变".nslog();
    }else{
        @"可变的".nslog();
    }

如果一个对象是可变的,copy之后会返回新对象,我们比较这两个指针就可以了。里面是如何实现的,我们不再关心。

 

你可能感兴趣的:(iOS中怎么判断可变和不可变的坑(更正版))