NSTaggedPointerString,__NSCFConstantString,__NSCFString和NSString的关系?NSString为什么用copy?

STK12与Python联合仿真(一):环境搭建 STK仿真python接口,安装与测试 阅读详情

​​​​问题引入:
NSString都存储在堆区吗?会不会存在栈区,或者数据区呢?

NSString用copy修饰还是strong修饰?NSString调用copy和mutableCopy会创建一个新的内存空间吗?NSMutableString用copy修饰会导致什么样的后果?

一.各类型字符串的关系和存储方式
NSString和NSMutableString相信我们平时都用过n遍了,但NSString真的都是一个存储在堆区的对象吗?如果在不同区,对它们进行copy操作,内存地址又会是什么样呢?

几个需要注意的点:

内存地址由低到高分别为:程序区-->数据区-->堆区-->栈区

                                            其中堆区分配内存从低往高分配,栈区分配内存从高往低分配

1.继承关系:

NSTaggedPointerString(栈区)      ---> NSString

__NSCFConstantString(数据常量区)  ---> __NSCFString (堆区) --->NSMutableString --->NSString

 

2.对于NSStringFromClass()方法,字符串较短的class,系统会对其进行比较特殊的内存管理,NSObject字符串比较短,直接存储在栈区,类型为NSTaggedPointerString,不论你NSStringFromClass多少次,得到的都是同一个内存地址的string;但对于较长的class,则为__NSCFString类型,而NSCFString存储在堆区,每次NSStringFromClass都会得到不同内存地址的string

3.__NSCFConstantString类型的字符串,存储在数据区,即使当前控制器被dealloc释放了,存在于这个控制器的该字符串所在内存仍然不会被销毁.通过快捷方式创建的字符串,无论字符串多长或多短,都是__NSCFConstantString类型,存储在数据区.

下面是实际代码测试的结果,对象内存地址和指针内存地址都作了相应注释:
 

    NSString *str1 = @"abcdeefghijk";//该种方式无论字符串多长,都是__NSCFConstantString类型,存储在数据区,0x0000000104b2c400
    NSString *strDigital = @"999";//即使很短,也是(__NSCFConstantString *)类型, 0x00000001092b1420,存储在数据区
 
    
    NSString *str1Copy = [str1 copy];//__NSCFConstantString,NSString类型的str1进行copy是浅拷贝,并不会拷贝一份新的内存地址,0x0000000104b2c400,内存地址和str1相同
    NSMutableString *str1MutableCopy = [str1 mutableCopy];//__NSCFString,NSString类型str1进行mutableCopy后是深拷贝,0x0000600000d7d590
    
    
    NSMutableString *str1MutaCopyCopy = [str1MutableCopy copy];//__NSCFString,mutableString类型的str1MutableCopy进行mutableCopy后是深拷贝,0x0000600000373980
    [str1MutableCopy appendString:@"12"];
   [str1MutaCopyCopy appendString:@"34"];//本行代码崩溃,原因是mutableString进行copy虽然是深拷贝,但返回的是不可变类型,只有NSMutableString才有appendString方法,__NSCFString没有appendString方法;虽然用NSMutableString接收,但str1MutaCopyCopy的类型还是由实际运行过程决定
    
    
    NSString * cfStringLongClass = NSStringFromClass([ViewController class]);//较长类情况下,该方法获得的字符串是类型__NSCFString存储在堆区,0x00006000003739a0
    NSString *taggedStrShortClass = NSStringFromClass([NSObject class]);//较短类情况下,该方法获得的字符串是NSTaggedPointerString类型,存储在栈区,0x86b1d57ef6188519
    
    NSString *taggedStrShortClassCopy = [taggedStrShortClass copy];//(NSTaggedPointerString *) $0 = 0xac71e37414f16209 @"NSObject" 内存地址不会变,浅拷贝,值也相同
    
    NSString *taggedStrShortClassMutaCopy = [taggedStrShortClass mutableCopy];//(__NSCFString *) $2 = 0x00006000036f4030 @"NSObject",内存地址变化,深拷贝一份至堆区,值相同,
 
    NSObject *obj = [[NSObject alloc]init];//对象存储在堆区,0x0000600000c61160
    
    
 
    
    //总结:stringWithFormat方式,最终字符串的类型由字符串长度决定,少于10个字符类型为NSTaggedPointerString,否则为__NSCFString类型
    NSString *strFormatLong = [NSString stringWithFormat:@"%@",@"01234567a909"];// ; 当长度超过9时,为__NSCFString,0x00006000003f6680,堆区
    NSString *strFormatShort = [NSString stringWithFormat:@"%@",@"012345678"];//当字符长度位数为9或以下时,strFormat为NSTaggedPointerString,0xfc16f577dc1ba4f7,存储在栈区
    
    NSString *strShortConstantCopy = [@"999" copy];//__NSCFConstantString,0x00000001092b1420,数据区.NSString调用copy是浅拷贝,和strDigital内存地址相同
    NSString *strShortConstantMutaCopy = [@"999" mutableCopy];//__NSCFString,0x0000600003fad410,堆区,NSMutable类型的string调用mutalbeCopy是深拷贝,返回一个b可变类型字符串;调用copy也是深拷贝,返回不可变字符串
    
    
    //从以下两个对象的内存地址可以得出结论:stringWithFormat不论接收什么类型的字符串参数,也无论它在数据区栈区还是堆区,都遵守长度临界值9的规则
    NSString *strShortConstantMutaCopyFormat = [NSString stringWithFormat:@"%@",strShortConstantCopy];//NSTaggedPointerString,0x8b25a274d8732690
    NSString *strShortConstantCopyFormat = [NSString stringWithFormat:@"%@",strShortConstantMutaCopy];//NSTaggedPointerString,0x8b25a274d8732690

二.NSString为什么用copy,copy修饰词到底做了什么工作?NSMutableString用copy修饰又如何?
测试主要注重下面几方面:

1.NSString分别用copy和strong修饰

2.来源为可变字符串和来源为不可变字符串

3.修改字符串之前和修改字符串之后

注意:

1.不可变类型的字符串是无法更改内容的,这里说的修改其实是修改它的指针,让它指向另一块内存,所以不会影响self.string;

         而可变字符串是可以更改内容的,对于他的修改是修改这块内存的内容.

2.copy修饰词起作用是在setter方法中发生的,如果通过_string_copy = [NSMutableString new];设置,得到的self.string_copy仍然  

          是浅拷贝

3.一个对象的类型是由运行时决定的,和@property中的声明无关,OC对于类型不匹配只会报警告,编译可以通过,但并不代表你执行  

          时候就不会出错.

4.NSString +copy ( 浅拷贝,返回不可变对象)  NSString+mutableCopy(深拷贝,返回可变对象) NSMutableString+copy(深拷贝,返回不可变对象) NSMutableString+mutableCopy(深拷贝,返回可变对象)

依然先上代码,看运行结果,内存地址和相关注释如下: 

@property (nonatomic, copy) NSString *string_copy;
@property (nonatomic, strong) NSString *string_strong;
 
@property (nonatomic, copy) NSMutableString   *string_muta_copy;
@property (nonatomic, strong) NSMutableString   *string_muta_strong;
@property (nonatomic, strong) UIView   *string_obj;
 
 
 NSString *string = [NSString stringWithFormat:@"%@",@"1234567890"];//p/x string (__NSCFString *) $0 = 0x0000600003e31800 @"1234567890"
    self.string_copy = string;// p/x _string_copy (__NSCFString *) $1 = 0x0000600003e31800 @"1234567890"
    self.string_strong = string;//p/x _string_strong (__NSCFString *) $2 = 0x0000600003e31800 @"1234567890"
    
    self.string_muta_copy = string;//(__NSCFString *) $1 = 0x0000600003e31800 @"1234567890"
    self.string_muta_strong = string;//(__NSCFString *) $2 = 0x0000600003e31800 @"1234567890"
    self.string_obj = string;//(__NSCFString *) $2 = 0x0000600003e31800 @"1234567890",类型是由具体运行过程决定的,即便用UIView接收它,也并没有影响string_obj的类型
    
    string = [NSString stringWithFormat:@"%@",@"abcdefghijklmn"];//p/x string (__NSCFString *) 0x0000600002d36dc0 @"abcdefghijklmn"
    /*
     一.来源是不可变字符串(修改前):
     a.当string的来源是非mutable类型时,不论是copy还是strong修饰,最终都只会仅仅拷贝一个指针,并不拷贝这块值的内存,因为这块内存存储的字符串
     本来就是非mutable,即不可修改类型的,深拷贝一份
     (lldb) p/x string
     (__NSCFString *) $0 = 0x0000600002d36da0 @"1234567890"
     (lldb) p/x _string_copy
     (__NSCFString *) $1 = 0x0000600002d36da0 @"1234567890"
     (lldb) p/x _string_strong
     (__NSCFString *) $2 = 0x0000600002d36da0 @"1234567890"
     
     一.来源是不可变字符串(修改后):
 -------->    此处开始修改源串string的值------>string = [NSString stringWithFormat:@"%@",@"abcdefghijklmn"];
     (因为string本身是不可变的,所以:虽然说修改string的值,倒不如说实际上是修改string这个指针,让string这个指针指向另一块内存区域,
     故结果是不会影响self.string_copy,self.string_strong所指向的那块内存)
     
     (lldb) p/x string
     (__NSCFString *) $3 = 0x0000600002d36dc0 @"abcdefghijklmn"
     (lldb) p/x _string_copy
     (__NSCFString *) $4 = 0x0000600002d36da0 @"1234567890"
     (lldb) p/x _string_strong
     (__NSCFString *) $5 = 0x0000600002d36da0 @"1234567890"
     (lldb)
     
     */
    
    
    
    
    
    NSMutableString *strMuta = [[NSMutableString alloc]initWithString:@"一二三四"];//p/x &strMuta  (NSMutableString **) $7 = 0x00007ffee4d919a0
    
    self.string_strong = strMuta;// p/x &_string_strong (NSString **) $6 = 0x00007f8c5fc0d788
    
    self.string_copy = strMuta;//p/x &_string_copy (NSString **) $8 = 0x00007f8c5fc0d780
    
    
    self.string_muta_strong = strMuta;//(__NSCFString *) $0 = 0x000060000032d500
    self.string_muta_copy = strMuta;//(__NSCFString *) $2 = 0x0000600000d264e0
    [self.string_muta_copy appendString:@"1234"];//崩溃,原因是:copy修饰的string_muta_copy在接收到字符串时,无论是可变还是不可变,都给你深拷贝一遍,NSMutableString调用copy方法虽是深拷贝,但返回的是不可变对象,不可变对象是没有appendString方法的
    /*
     二:来源是可变字符串(修改前)
     0.未修改源muta字符串时,可以看出:copy修饰的string_copy拷贝了一份内存,即值和strMuta一样,但实际存储这个字符串值的内存不是同一块.
     而strong修饰的string_strong只拷贝了一份指针,并没有拷贝存储这块值的内存,实际上只是指针不是同一个,指向的内存还是同一块
     (lldb) p/x strMuta
     (__NSCFString *) $0 = 0x000060000318ab20 @"一二三四"
     (lldb) p/x _string_copy
     (__NSCFString *) $1 = 0x0000600003f88120 @"一二三四"
     (lldb) p/x _string_strong
     (__NSCFString *) $2 = 0x000060000318ab20 @"一二三四"
     
     */
    
    [strMuta appendString:@"1234"];
    /*
     二.来源是可变字符串(修改后)
     1.修改源字符串strMuta后,由于string_copy指针指向新拷贝的那一块内存区域-->0x0000600003f88120,所以修改源串strMuta的那
     块内存-->0x000060000318ab20不会影响copy修饰的字符串;而string_strong只是拷贝了一个指针,这个指针仍然指向-->0x000060000318ab20这
     块区域,和源串是同一块内存,唯一不同的就是指针本身地址不同,而指针的内容是相同的,都存储着源串的内存地址,修改源串导致string_strong存储的值也
     随之变化
     
     lldb) p/x strMuta
     (__NSCFString *) $3 = 0x000060000318ab20 @"一二三四1234"
     (lldb) p/x _string_copy
     (__NSCFString *) $4 = 0x0000600003f88120 @"一二三四"
     (lldb) p/x _string_strong
     (__NSCFString *) $5 = 0x000060000318ab20 @"一二三四1234"
     
     
     */

从上面代码运行的结果分析,不难得出:其实copy就是在setter方法里起了特殊作用,利用copy修饰的string,在setter方法中进行一次判断,a.如果来源是可变字符串,就深拷贝一份(为什么深拷贝?因为来源是可变字符串,这串字符就可能会被修改,如果不深拷贝一份的话,将来源串不小心被修改了,你的self.string也会跟着变化,如果发生了不可预见的结果,你肯定要怪xcode了,这个结果是你不希望发生的);b.如果来源是不可变字符串,就直接赋值,不拷贝内容(为什么只拷贝指针不拷贝内容?因为来源为不可变,你就算改变self.string也只能通过重新赋值来改变,赋值肯定是你自己操作的,如果因为重新赋值发生了不可预见的问题,那就是你自己的责任了)

从结论中我们可以推测NSMutableString不用copy修饰的原因了:如果你用copy去修饰一个NSMutableString的字符串属性string_muta_copy,如果将来你把一个不可变来源通过set方法赋值给这个属性,set方法内部会因为这个来源是不可变的进行一次copy,copy后再将新的对象赋给_string_muta_copy,这时候的拷贝是深拷贝,但返回的是不可变对象,而在你声明中你认为这个对象是可变的,编译时期也会被认为是可变的,你向他发送NSMutableString的方法消息不会报错,但到了运行时候回因为string_muta_copy是个不可变字符串而找不到方法.

对于NSMutableString类型的属性,我们在对它赋值时,最好确保是可变类型,防止以后你把它当做可变字符串,进行拼接操作,而实际上它却被你赋值了不可变字符串而出错

 

至此:大概讲述了NSString和NSMutableString调用copy和mutableCopy.修饰词用copy和strong的原因.
          文章如有不对的地方还请尽快与我联系.我会尽快做出修改,以免错误误导到别人.QQ:422538722

 

另外:我们通过把代码编译成C++文件,可以看出copy修饰的属性和strong修饰的属性,在底层的处理是不同的,下面是源码节选:
 

 
//ViewController对象在底层实则是一个结构体,它的每个属性都将作为该类型结构体的一个成员
struct ViewController_IMPL {
	struct UIViewController_IMPL UIViewController_IVARS;
	NSString *_string_copy;
	NSString *_string_strong;
	NSMutableArray *_array_muta_copy;
	NSMutableArray *_array_muta_strong;
	NSArray *_array_copy;
	NSArray *_array_strong;
};
 
//分别代表_string_copy和_string_strong在ViewController_IMPL结构体中的偏移量,通过偏移量+结构体内存地址就可以找到这个成员
extern "C" unsigned long OBJC_IVAR_$_ViewController$_string_copy;
extern "C" unsigned long OBJC_IVAR_$_ViewController$_string_strong;
 
 
 
 
 
// self.string_copy = string;
  ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)self, sel_registerName("setString_copy:"), (NSString *)string);
 
// self.string_strong = string;
    ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)self, sel_registerName("setString_strong:"), (NSString *)string);
 
 
 
//相当于_string_copy的getter方法,取_string_copy时,返回结构体里的该成员
static NSString * _I_ViewController_string_copy(ViewController * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_ViewController$_string_copy)); }
 
//OC中对copy修饰的属性所做的处理,这个方法下面会有详细说明
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
 
//相当于_string_copy的setter方法,可以看见,内部是调用了objc_setProperty方法做特殊处理的
static void _I_ViewController_setString_copy_(ViewController * self, SEL _cmd, NSString *string_copy) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct ViewController, _string_copy), (id)string_copy, 0, 1); }
 
 
//_string_strong的getter方法
static NSString * _I_ViewController_string_strong(ViewController * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_ViewController$_string_strong)); }
 
//_string_strong的setter方法,可以明显看到和copy修饰的属性处理不一样,没有调用objc_setProperty方法
static void _I_ViewController_setString_strong_(ViewController * self, SEL _cmd, NSString *string_strong) { (*(NSString **)((char *)self + OBJC_IVAR_$_ViewController$_string_strong)) = string_strong; }

关于objc_setProperty:

objc-runtime源码里检索关键词,来到这里:

#define MUTABLE_COPY 2
 
void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy) 
{
//当shouldCopy为真,且不等于2(MUTABLE_COPY)时,copy为YES,一般objc_setProperty方法调用时会给shouldCopy传0,1,2(一般来说,0代表不copy,1代表copy,2代表mutableCopy)
    bool copy = (shouldCopy && shouldCopy != MUTABLE_COPY);
 
//当shouldCopy为2时,mutableCopy为YES
    bool mutableCopy = (shouldCopy == MUTABLE_COPY);
 
    reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy);
}
 
 
对比上面传进来的参数:
objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct ViewController, _string_copy), (id)string_copy, 0, 1)
可以看出参数依次传入了self,_cmd,偏移量,string_copy,非atomic,copy为YES
 
 
 
构造好参数之后,实际上是调用了reallySetProperty函数,下面查看该函数:
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
//当offset为0时所做的处理,因为结构体第一个成员都是isa,如果offset为0代表是更改isa成员
    if (offset == 0) {
        object_setClass(self, newValue);
        return;
    }
 
//旧值
    id oldValue;
    id *slot = (id*) ((char*)self + offset);
//当copy为YES时,调用copyWithZone方法
    if (copy) {
        newValue = [newValue copyWithZone:nil];
    } else if (mutableCopy) {
//当mutableCopy为YES时,调用mutableCopyWithZone方法
        newValue = [newValue mutableCopyWithZone:nil];
    } else {
//如果objc_setProperty最后一个传0的话,则仅仅对该属性进行一次retain强引用
        if (*slot == newValue) return;
        newValue = objc_retain(newValue);
    }
 
 
 
//设置新值newValue,释放旧值oldValue
    if (!atomic) {
//非原子情况下的操作
        oldValue = *slot;
        *slot = newValue;
    } else {
//原子情况下的操作
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock();
        oldValue = *slot;
        *slot = newValue;        
        slotlock.unlock();
    }
 
    objc_release(oldValue);
}

 

【数据分析】R语言分段结构方程模型手把手教程(Piecewise Structural Equation Model) 分段结构方程模型(Piecewise Structural Equation Model, SEM)是一种用于分析变量之间因果关系的统计方法。它通过将复杂的因果关系分解为多个简单的线性模型来评估变量之间的直接和间接效应。与传统的结构方程模型(SEM)不同,分段结构方程模型不需要假设数据的多变量正态分布,因此在处理非正态数据时更为灵活。 阅读详情

相关推荐

手把手教你给STM32F103移植LVGL触摸驱动(基于野火开发板,附完整代码)

本文详细介绍了如何在野火STM32F103开发板上移植LVGL触摸驱动,提供从环境准备到代码实现的完整指南。通过XPT2046触摸芯片的底层驱动集成和LVGL输入设备接口配置,开发者可以快速实现触摸功能,并解决常见问题如触摸无响应、坐标偏移等。

weixin_30856725的博客 1021

iOS NSString详解

一:__NSCFConstantString      __NSCFString        NSTaggedPointerString 二:weak修饰,字符串内存管理 三:NSTaggedPointerString讲解 四:面试题 五:__NSCFString:Toll-free bridgin桥接机制(接上面一)   OC中的NSString不论是在编译时还是在运行时都做了很多...

qq_27909209的博客 1495

把MinerU集成到Dify

本文介绍了如何将本地部署的MinerU与Dify平台进行集成。首先需要确保Dify和MinerU在Docker环境中正常运行,并通过配置虚拟网络实现互联。然后详细说明了在Dify平台安装MinerU插件的步骤,包括从插件市场搜索安装、配置连接参数等关键操作。特别强调了要等待MinerU容器完全启动(healthy状态)后再进行Dify配置,否则会出现连接错误。通过简单的URL指向和API密钥设置,用户即可实现Dify平台与本地MinerU算力网络的对接,为后续的AI应用开发提供基础支持。

lyxerlau的博客 313

【OC】NSString的三种实现方式

通过阶段性的学习,我们iOS小组进行了组内考核,在主观题回答时,对于NSString的三种实现方式,我没有弄明白,所以有了这篇学习笔记。

2301_80467753的博客 1309

避坑指南:Allegro 17.2更新封装时遇到的5个典型问题及解决方案(含Symbol报错处理)

本文深度解析Allegro 17.2封装更新过程中的核心机制与常见陷阱。针对“Update Symbols”功能失效、焊盘不匹配、DRC报错、图形层叠错误等5大典型问题,提供从原理分析到实战解决方案的完整指南,帮助用户实现从“更新失败”到“丝滑替换”的平稳过渡。

tgb34567890的博客 1039

阿里云百炼平台创建智能体-上传文档

阿里云百炼智能体-上传文档文件

weixin_43930851的博客 1356

iOS-深入理解NSString的三种存储类型

在 Objective-C 的 Fondation 框架中 NSString 对象是很复杂的存在,各种方式创建以及不同长度的字符串都会影响 NSString 对象在内存中所处的位置。Objective-C 在运行时也对其做了很多优化。今天就来研究一下 NSString 这个复杂的对象。 打印结果 对于这个类型的NSString,我们测试打印他的retainCount 类型和地址 创建两个内容一样的 __NSCFString 他们的地址是不一样的 引用计数 查阅资料 和 __NSCFCo

weixin_61639290的博客 1281

jlink驱动安装

jlink驱动下载安装及keil识别

qq_43868701的博客 3万+

NSCFString与NSString类型的字符串导致的崩溃问题

今天在做项目时,遇到一个奇怪的问题: NSString *account = [Tool getUserName];  // [Tool getUserName]得到的值为@“liuyao" NSString *account = @"liuyao"; 通过第一种方式创建的account在JSONKit中会导致程序崩溃。于是开始寻找原因,后来发现,两种

mygrilzhuyulin的专栏 6021

ZW3D 二次开发-制作插件

1.Windows 7 SP1 或 Windows 10 或 Windows 11(推荐 Windows 11)2.Visual studio 2017-2022 (或 C/C++的任何其他集成开发环境)(推荐 Visual studio 2022)3.ZW3D 2023 或以上版本(建议使用与 ZW3D 一致的 API 的版本)4.Qt5.9.7(for Windows)博主学习使用环境的是:Windows 11 Version 24H2 + Visual studio 2022 + Qt5.9.7(fo

fhqiwmc的博客 810

Autosar诊断实战系列05-Dcm之0x27加解密服务配置开发详解

UDS 0x27服务实战开发介绍,对解锁尝试次数及delay时间进一步解释。

initiallizer的博客 1991

【iOS】NSString的三种实现方式

最近被学长问到了有关NSString底层的三种实现方式,但是回答不上来,特此撰写博客记录本文讲述了NSString的三种实现方式,接下来总结一下学到的知识我们一般通过@“…”、CFSTR(“…”)或者方法来生成这种类型这种对象存储在常量区,是一种编译时常量,同时还是一种单例好处是可以提高字符串的访问效率,并且节省内存空间通过 NSString 的等方法创建的 NSString 对象一般都是这种类型。他并不是一种字符串常量。所以和其他的对象一样在被创建时获得了 1 的引用计数。

weixin_72437555的博客 1246

05 SAP CPI 访问第一个CPI接口

其中的clientid的值可作为Basic验证的用户名,clientsecret的值可作为Basic验证的密码。点击SEND按钮,可看见返回状态为200 OK。在04中,我们得到TOKEN令牌。POSTMAN向下滚动。点击按钮获取token。

SAP CPI 662

NSString的内存管理之 __NSCFConstantString、NSTaggedPointerString、__NSCFString

> 转自:http://skyfly.xyz/2015/11/08/iOS/NSString%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/  by skyfly   在 Objective-C 的 Fondation 框架中 NSString 对象是很复杂的存在,各种方式创建以及不同长度的字符串都会影响 NSString 对象在内存中所处的...

王学森的专栏 6886

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

NSString的类型

以下代码关闭了ARC,定义了一个宏,便于我们查看输出 #define MLog(_var) ({NSString* name = @#_var;NSLog(@"%@: %@ -> %p -> %@ -> %d",name,[_var class],_var,_var,(in...

chuaijiongli3832的博客 339

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

[iOS]-NSString的三种管理方式

[iOS]-NSString的三种管理方式浅谈

m0_52192682的博客 433

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

[iOS开发]NSString的三种类型管理方式

文章目录参考博客问题发现:__NSCFConstantString__NSCFStringNSTaggedPointerString标签指针的概念NSString的深浅复制问题 参考博客 NSString的内存管理 iOS里的TaggedPointer[NSString篇] 问题发现: NSString *firstString = @"helloworld"; NSString *secondString = [NSString stringWithFormat:@"helloworld"];

复杂化的博客 1137

NSString类的底层实现知识汇总与易错点梳理

NSString的底层实现原理与字符串知识汇总。

2505_93363502的博客 449

NSStrig的三种形式

和。是不可变的字符串常量,它是在编译时创建的,存储在常量区,且在程序生命周期内不可修改。多个相同的字符串常量在内存中只会存储一份。是不可变的字符串对象,基于动态分配的内存,可以包含任意长度的字符序列。当使用字符串字面量或调用相关的初始化方法创建不可变字符串时,会生成一个对象。是一种优化方式,在64位环境下用于存储小的对象或数字值。它将数据直接存储在指针中,而不需要额外的内存分配。当字符串的长度小于等于9且只包含数字、英文字母等特定字符时,会自动成为对象。在进行复制操作时,可以使用copy或方法。copy。

aa2002aa的博客 798

[iOS开发]NSString的类型

一个关于字符串三种类型的简要探索

weixin_52192405的博客 221

搜狗2015iOS笔试题详解:内存管理、Runtime与GCD核心考点

在iOS开发中,内存管理与Runtime机制是面试和工程实践的核心。ARC(自动引用计数)通过编译器自动插入retain/release,但属性关键字copy与strong的选择、weak的底层实现、autoreleasepool的释放时机等细节,仍是区分开发者水平的关键。深入理解Objective-C的消息发送流程,可解决方法动态解析、循环引用等常见问题。GCD作为并发编程的重要工具,其同步/异步与死锁原理直接影响App性能。这些基础概念广泛应用于图片缓存、网络请求优化等场景。搜狗2015年iOS笔试题正

weixin_30074763的博客 329

NSString NSCFString区别

NSString是 NSCFString的父类 在于NSString是个class cluster,一个类簇。什么是一个类簇?简单的来说,NSString是个“工厂类”,然后它在外层提供了很多方法接口,但是这些方法的实现是由具体 的内部类来实现的。当使用NSString生成一个对象时,初始化方法会判断哪个“自己内部的类”最适合生成这个对象,然后这个“工厂”就会生成这个具体 的类对象返回给你。这...

weixin_30629653的博客 524

【iOS安全】NSTaggedPointerString和__NSCFString

【iOS安全】NSTaggedPointerString和__NSCFString

Juruo@Security 915

iOS开发之'-[__NSCFString appendString:]: nil argument'

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString appendString:]: nil argument' *** First throw call stack: (     0   CoreFoundation               

坤宇的博客 4123

__NSCFString containsString:]: unrecognized selector sent to instance 的解决方案

代码: [objc] view plaincopyprint? NSString *urlString = [[request URL] absoluteString];   if([urlString containsString:@"mark"])   {      // do something   }   这段代码,没有

u011862058的专栏 1298

NSString的三种类型

和 __NSCFConstantString 不同, __NSCFString 对象是在运行时创建的一种 NSString 子类,他并不是一种字符串常量。对于 NSString 对象来讲,当非字面值常量的数字,英文字母字符串的长度小于等于 9 的时候会自动成为 NSTaggedPointerString 类型。当我们使用不同的字符串对象进行创建时当内容相同,其对象的地址也相同。当我们使用不同的字符串对象进行创建时当内容相同,其对象的地址也相同,这也就证明了常量字符串是一种单例。这种对象存储在字符串常量区。

m0_73974056的博客 418
上一篇: NSTimer 循环引用分析与解决方案
下一篇: Objective-C 对象存储在堆上而不是栈上 why?
LIN1986LIN
博客等级 码龄19年 17粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值