ios - 为什么 isKindOfClass 和 isMemberOfClass 与 NSString 和 NSMutableString 配合不好?

标签 ios class nsstring objective-c-runtime nsmutablestring

我知道Apple has cautioned反对使用它。但鉴于他们的推理,结果远非相关和预期。

这是我的调试输出 - 结果在代码中没有什么不同 - 下面只是为了简洁:

(lldb) po [@"Hello" isKindOfClass:[NSMutableString class]]
true => A mutable string?

(lldb) po [[@"Hello" mutableCopy] isKindOfClass:[NSMutableString class]]
0x00000001019f3201   => What's that?

(lldb) po [[@"Hello" mutableCopy] isMemberOfClass:[NSMutableString class]]
0x000000010214e400   => What's that?

(lldb) po [@"Hello" isMemberOfClass:[NSMutableString class]]
false  => Once again?

除此之外,我删除了所有字符串文字代码并测试了以下内容:
NSMutableString * m = [[NSMutableString alloc] initWithString:@"Hello"];

bool b = [m isKindOfClass:[NSMutableString class]];
NSLog(@"%d", b); --> 1 Expected.
b = [m isKindOfClass:[NSString class]];
NSLog(@"%d", b); --> 1 Expected.
b = [m isMemberOfClass:[NSString class]];
NSLog(@"%d", b); --> 0 Expected.
b = [m isMemberOfClass:[NSMutableString class]];
NSLog(@"%d", b); --> 0 Not Expected.

有启示吗?

更新:

苹果自己的看法:

Be careful when using this method on objects represented by a class cluster. Because of the nature of class clusters, the object you get back may not always be the type you expected. If you call a method that returns a class cluster, the exact type returned by the method is the best indicator of what you can do with that object.



为什么不简单地说不雇用isKindOfClassisMemberOfClass与集群类?

该解释防止从以下角度使用:

You might end up modifying something that you are not supposed to.



而不是说:

These methods do not work with class clusters. (in the examples, I have shown above - I am clearly passing correct objects and still not getting expected results.)



更新 2:

归档于 Apple Radar .

最佳答案

正如您在评论中声称的那样,这些方法不会“误导”。因为NSStringNSMutableString是类簇,它们可以返回任何具体子类的实例,它是-a NSStringNSMutableString , 分别。

碰巧的是,NSString 中的大多数具体子类cluster 也是 NSMutableString 的子类.他们没有使用实际的类来控制可变性,而是使用标志或类似的东西。所有完全有效并符合设计契约(Contract)。

所以,这就是为什么 [@"Hello" isKindOfClass:[NSMutableString class]]返回真。你问“可变字符串?”不,该表达式不是对可变性的有效测试。如文件所述,有 没有可变性的有效测试。这是你误解的核心。您不得尝试询问对象的类以确定它是否是可变的。您必须尊重 API 中指针的静态类型。

编辑:这记录在 Concepts in Objective-C Programming: Object Mutability – Receiving Mutable Objects :

Use Return Type, Not Introspection

To determine whether it can change a received object, the receiver of a message must rely on the formal type of the return value. If it receives, for example, an array object typed as immutable, it should not attempt to mutate it. It is not an acceptable programming practice to determine if an object is mutable based on its class membership—for example:

if ( [anArray isKindOfClass:[NSMutableArray class]] ) {

    // add, remove objects from anArray

}

For reasons related to implementation, what isKindOfClass: returns in this case may not be accurate. But for reasons other than this, you should not make assumptions about whether an object is mutable based on class membership. Your decision should be guided solely by what the signature of the method vending the object says about its mutability. If you are not sure whether an object is mutable or immutable, assume it’s immutable.

A couple of examples might help clarify why this guideline is important:

  • You read a property list from a file. When the Foundation framework processes the list, it notices that various subsets of the property list are identical, so it creates a set of objects that it shares among all those subsets. Afterward you look at the created property list objects and decide to mutate one subset. Suddenly, and without being aware of it, you’ve changed the tree in multiple places.

  • You ask NSView for its subviews (with the subviews method) and it returns an object that is declared to be an NSArray but which could be an NSMutableArray internally. Then you pass that array to some other code that, through introspection, determines it to be mutable and changes it. By changing this array, the code is mutating internal data structures of the NSView class.

So don’t make an assumption about object mutability based on what introspection tells you about an object. Treat objects as mutable or not based on what you are handed at the API boundaries (that is, based on the return type). If you need to unambiguously mark an object as mutable or immutable when you pass it to clients, pass that information as a flag along with the object.



正如其他人所提到的,-isMemberOfClass:测试是否是该确切类的实例而不是任何子类。对于类集群,这将始终返回 false,因为公共(public)类是抽象的并且永远不会有实例。

其他奇怪的结果可能是因为您使用的是 po (“打印对象”的缩写)用于非对象值。使用 p bool 表达式的命令。

关于ios - 为什么 isKindOfClass 和 isMemberOfClass 与 NSString 和 NSMutableString 配合不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34561101/

相关文章:

iphone - refreshObject 如何在嵌套的托管对象上下文中工作?

ios - 如何在与 panGestureRecoginizer 的交互转换中使用 pushViewController

java - JavaFX 节点的父类可以通过访问/确定吗?

objective-c - 如何获取 NSString 例如 "0+1+2",获取它们的总和并创建新字符串。对象C

objective-c - NSMutableURLRequest POST 消息中的 Base64 问题?

swift - 如何在 swift 中简单地连接到 NSString

在 Swift 中为 iPAD 开发 iOS 应用程序

ios - 嵌入式二进制验证实用程序错误

Python:从子类更改父类属性

c++ - 在类中创建一个空的动态数组,访问时赋值?