iOS中怎么判断可变和不可变的坑(更正版)
iOS中怎么判断可变和不可变的坑
怎么判断NSString和NSMutableString呢
看题
BOOL result = [@"" 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:@""];//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:@""];//__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。
转注出:原文
===========更正===========================
上面的方法在实际使用中被证明是错的,看如下两个方法
//在有的版本中执行结果如下
@().description;//__NSCFString->NSMutableString->NSString
[NSString stringWithFormat:@"123%d",]//__NSCFString->NSMutableString->NSString
就是说这两种情况从外部审查类型来看,根本和[NSMutableString new]的效果是一样的,而且是响应下面的方法的
[xxx respondsToSelector:@selector(appendFormat:)];
但是实际的情况是一调用就崩溃了。不听老人言吃亏在眼前,真的是最打脸的道理最朴素。一个不开源的东西,我们就是喜欢在外面赌博。
思考了很久我发现了解决之道,大道果然至简:我不知道它怎么实现的,但是苹果知道……
所以:
id copyed = [xxx copy];
if(copyed == xxx){
@"不可变".nslog();
}else{
@"可变的".nslog();
}
如果一个对象是可变的,copy之后会返回新对象,我们比较这两个指针就可以了。里面是如何实现的,我们不再关心。
iOS中怎么判断可变和不可变的坑(更正版)的更多相关文章
- iOS 中如何判断当前是2G/3G/4G/5G/WiFi
5G 什么的,还得等苹果API更新啊,不过将来还是这个处理过程就是了. 关于判断当前的网络环境是2G/3G/4G,这个问题以前经常看到,最近在一工程里看到了如果判断的API.而在撸WebRTC音视频通 ...
- IOS中如何判断APP是否安装后首次运行或升级后首次运行
对于是否为首次安装的App可以使用如下方法来判断 [[NSUserDefaults standardUserDefaults] boolForKey:@"firstLaunch"] ...
- ios中怎么样判断路径最后的后缀名称
使用hasSuffix属性即可 例如 [photo.thumbnail_pic.lowercaseString hasSuffix:@"gif"]
- IOS 中runtime 不可变数组__NSArray0 和__NSArrayI
IOS 中runtime 不可变数组__NSArray0 和__NSArrayI 大家可能都遇到过项目中不可变数组避免数组越界的处理:runtime,然而有时候并不能解决所有的问题,因为类簇不一样 # ...
- python中的可变与不可变对象
Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...
- Java中的String为什么是不可变的?
转载:http://blog.csdn.net/zhangjg_blog/article/details/18319521 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那 ...
- php学习笔记5--php中的可变变量,可变函数及匿名函数
可变变量指的是:将一个变量的值再次当做一个变量名从而得到另外一个变量的值.如:$name = 'dqrcsc';$myname = 'name'; //$myname的值碰巧是另一个变量的变量名ech ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- IOS开发中如何判断程序第一次启动(根据判断结果决定是否显示新手操作引导)
IOS开发中如何判断程序第一次启动 在软件下载安装完成后,第一次启动往往需要显示一个新手操作引导,来告诉用户怎么操作这个app,这就需要在程序一开始运行就判断程序是否第一次启动,如果是,则显示新手操作 ...
随机推荐
- Html5 锚 <a>的页内跳转, name=abc herf=#abc
锚点是网页制作中超级链接的一种,又叫命名锚记.命名锚记像一个迅速定位器一样是一种页面内的超级链接,运用相当普遍. 英文名:anchor 使用命名锚记可以在文档中设置标记,这些标记通常放在文档的特定主题 ...
- log4net.dll添加报错
描述: 新建项目Log4Net类库项目,添加log4net.dll,封装Log类对日志进行操作 新建webForm项目添加Log4Net类库生成的dll生成日志,页面报错,未能加载文件或程序集log4 ...
- <Android 应用 之路> 百度地图API使用(4)
前言 百度地图的定位功能和基础地图功能是分开的,使用的是另外的jar包和so库文件,详情请关注官网: 百度定位SDK 配置 下载对应的jar包和so库,然后移动到lib目录下 AS中注意事项 sour ...
- LintCode2016年8月8日算法比赛----中序遍历和后序遍历构造二叉树
中序遍历和后序遍历构造二叉树 题目描述 根据中序遍历和后序遍历构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下 ...
- SVN - Checksum mismatch while updating
Go to the folder with the file causing problems Execute command svn update --set-depth empty (note: ...
- 利用Vagrant完成开发环境配置
作者:astaxie链接:https://github.com/astaxie/go-best-practice/blob/master/ebook/zh/01.0.md著作权归作者所有.商业转载请联 ...
- .net core系列之《将.net core应用部署到Ubuntu》
1.首先准备一个演示项目. 2.然后将这个项目用FileZilla工具上传到Ubuntu中. 3.进入目标文件,接下来有两种方法来部署项目 a.用dotnet run命令 root@hhz-virtu ...
- Kendo 计算字段
var Product = kendo.data.Model.define({ fields: { "quantity": { type: "number" } ...
- Activator 通过SSH解锁屏幕等手势操作
来源:https://qunwang6.github.io/blog/Activator/ Activator 发表于 2015-10-24 | 分类于 iOS Activator Activ ...
- apt安装mysql
使用 APT 安装 MySQL 参考官方文档 apt-get install mysql-server 这将安装MySQL服务器的包,以及客户端和数据库公共文件的包. 在安装过程中,系统会要求您为ro ...