美文网首页
NSSting 详解

NSSting 详解

作者: Ray_lawq | 来源:发表于2021-11-24 17:24 被阅读0次

    NSSting 类族

    NSSting 是一个类族(Class Clusters),最后生成的对象类型,取决于我们调用的初始化方法(Toll-free bridgin桥接机制 来实现)

    Toll-free bridgin桥接机制

    Toll-free bridging,简称为TFB,是一种允许某些ObjC类与其对应的CoreFoundation类(Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能)之间可以互换使用的机制。比如 NSString与CFString是桥接(bridged)的, 这意味着可以将任意NSString当做CFString使用,也可以将任意的CFString当做NSString使用。

    原理(拿NSString举例)大概是:NSString是一个抽象类,每当你创建一个NSString实例,实际上是创建的NSString的一个私有子类实例。其中一个私有子类就是NSCFString,其是CFString类的在ObjC中的对应类。NSCFString实现了作为NSString需要的所有方法。
    我的理解:总之,你知道有Toll-Free Bridging桥接机制,然后NSCFString是NSString的私有子类,实现了它的所有方法。

    iOS 支持Toll-free bridgin的类 iOS 支持Toll-free bridgin的类

    NSSting 类型:

    NSCFConstantString:常量类型,保存在常量区,有时候也在栈区,引用计数同样为-1
    NSCFString:堆区, 引用计数同样为 1
    NSTaggedPointerString:优化的NSCFString,引用计数同样为-1

    NSTaggedPointerString (0-9位是taggedpointer类型)
    对于64位程序,为了节省内存和提高运行速度,苹果引入了 Tagged Point 技术
    NSTaggedPointerString是对NSCFString优化后的存在,在运行时创建时对字符串的内容和长度做出判断,若字符串内容是由ASCII字符构成且长度较小(大概十个字符以内),这时候创建的字符串就是NSTaggedPointerString类型,字符串直接存储在指针里,引用计数同样为-1,不适用对象的内存管理策略。

    //类型=__NSCFConstantString, 地址=0x101d1a098
    static NSString *a = @"a";
    - (void)test {
    
        //类型=__NSCFConstantString, 地址=0x101d1a0d8
        NSString *a0 = @"aaa";
        NSString *a1 = [[NSString alloc] init];
        a0 = @"a0";
        NSString *a2 = [[NSString alloc] initWithString:a0];
        
        //类型=NSTaggedPointerString, 地址=0x89a6aa09cd52cc1f
        NSString *a3 = [NSString stringWithFormat:@"%s", "str2"];
        NSString *a4 = [NSString stringWithFormat:@"%d", 123];
        NSString *a5 = [NSString stringWithFormat:@"%d", YES];
        
        //类型=__NSCFString, 地址=0x60000032a5a0
        NSString *a6 = [[NSString alloc] initWithFormat:@"aaa"];
        //类型=__NSCFString, 地址=0x60000032a520,
        NSString *a7 = [NSString stringWithFormat:@"%@", @"aaa"];
        //类型=NSTaggedPointerString, 地址=0x89a6aa09cd52cc1f
        NSString *a8 = [NSString stringWithFormat:@"%@", a3];
        
        //类型=__NSCFString, 地址=0x600000d70de0
        NSMutableString *a9 = [NSMutableString stringWithFormat:@"%@", a0];
        NSMutableString *a10 = [NSMutableString stringWithFormat:@"%@", a3];
        NSMutableString *a11 = [NSMutableString stringWithFormat:@"%@", a6];
    }
    

    结论:

    1. 普通创建的字符串和 static 字符串都是 NSCFConstantString类型,如:a0 ~ a2。
    2. 使用 initWithFormat 方法创建,参数为基础数据类型(如:charboolint等等)或 NSTaggedPointerString 类型, 字符串都是 NSTaggedPointerString类型,如:a3~a5,a8。
    3. 使用initWithFormat 方法创建,参数为对象类型的,字符串是NSCFString 类型。如 a6~a7 和 a9 ~ a11

    Tagged Pointer

    Tagged Pointer专门用来存储小的对象,例如NSNumberNSDate
    Tagged Pointer指针地址保存的其实是(对象地址+值)。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。所以,它的内存并不存储在堆中,也不需要mallocfree
    在内存读取上有着3倍的效率,创建时比以前快106倍。
    由此看来,NSTaggedPointerString根本不是对象,是分配在栈区的

    copy and mutableCopy

    @property (nonatomic, strong) NSString *str;
    @property (nonatomic, strong) NSString *str1;
    
    @property (nonatomic, copy) NSString *str2;
    @property (nonatomic, copy) NSString *str3;
    
    - (void)test {
    
        //类型=__NSCFConstantString, 地址=0x10ca08098
        self.str = @"aaa";
        self.str1 = self.str;
    
        //str   类型=__NSCFConstantString, 地址=0x10ca08098
        //str1  类型=__NSCFConstantString, 地址=0x10ca08138
        self.str1 = @"bbb";
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        self.str2 = @"ccc";
        self.str3 = self.str2;
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        //类型=__NSCFConstantString, 地址=0x10ca081b8
        self.str3 = @"ddd";
    }
    
    - (void)test1 {
    
        //类型=__NSCFConstantString, 地址=0x10ca08098
        self.str = @"aaa";
        self.str1 = [self.str copy];
    
        //str   类型=__NSCFConstantString, 地址=0x10ca08098
        //str1  类型=__NSCFConstantString, 地址=0x10ca08138
        self.str1 = @"bbb";
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        self.str2 = @"ccc";
        self.str3 = [self.str2 copy];
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        //类型=__NSCFConstantString, 地址=0x10ca081b8
        self.str3 = @"ddd";
    }
    
    - (void)test2 {
    
        //类型=__NSCFConstantString, 地址=0x10ca08098
        self.str = @"aaa";
        //类型=__NSCFString, 地址=0x600003a60e70
        self.str1 = [self.str mutableCopy];
    
        //str   类型=__NSCFConstantString, 地址=0x10ca08098
        //str1  类型=__NSCFConstantString, 地址=0x10b926138
        self.str1 = @"bbb";
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        self.str2 = @"ccc";
        //类型= NSTaggedPointerString, 地址=0xaec7592a59dc294c
        self.str3 = [self.str2 mutableCopy];
    
        //类型=__NSCFConstantString, 地址=0x10ca08158
        //类型=__NSCFConstantString, 地址=0x10b9261b8
        self.str3 = @"ddd";
    }
    

    总结:

    1. 不管是 strong 还是 copy 修饰字符串属性,使用 = 赋值 和 copy 都会出现 swift 的 写时复制 的效果(而原来学习的时候,这2个关键字是深拷贝浅拷贝的区别,估计是系统在新版本给做了优化)。
    2. 使用mutableCopy 全部按照深拷贝去实现。
    3. 如果是局部变量,呈现的效果和属性是一样的。

    相关文章

      网友评论

          本文标题:NSSting 详解

          本文链接:https://www.haomeiwen.com/subject/xxastrtx.html