目标C中的类型转换失败

Pra*_*lli 0 casting objective-c ios

这里的类型铸造成功

id object = [NSMutableArray array];
NSURLConnection *urlCon = (NSURLConnection*)object;

if ([urlCon isKindOfClass:[NSURLConnection class]])
    NSLog(@"urlCon is NSURLConnection");
else if ([urlCon isKindOfClass:[NSMutableArray class]])
    NSLog(@"urlCon is NSMutableArray"); // this is called
Run Code Online (Sandbox Code Playgroud)

实际上因为'object'是类型NSMutableArray,所以类型转换NSURLConnection应该失败.但它是成功的,urlCon仍然指向NSMutableArray,那么TypeCasting有什么用?

Rob*_*Rob 7

有两个不同的问题:一个是变量的类型.另一个是底层对象的类型.

在Objective-C中,对象指针的转换不会改变底层对象的内容.在Objective-C中进行投射不会"成功"或"失败".它只是告诉编译器允许您将变量视为实际指向已转换类型的对象.通常在以下情况下执行此操作:(a)您对编译器无法合理知道的基础对象有一些了解,并且(b)您希望能够在没有编译器抱怨的情况下调用某个类的某个特定方法.很明显,这不是这里的情况,你把urlCon变量投射到期望object是a NSURLConnection,而不是.

但是isKindOfClass是运行时检查,它实际上是查看底层对象的类型,而不关心变量的类型.


一个常见的模式也将使用isKindOfClass确定对象是否是特定类的一个,如果是,则将其转换为该特定类型,以便您可以使用该类的方法和/或属性,而无需编译器发出警告.

因此,在处理网络请求时,您经常会看到这种模式:

NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {             // check to see if response is `NSHTTPURLResponse`
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;  // if so, cast `NSURLResponse` to `NSHTTPURLResponse`
        NSInteger statusCode = httpResponse.statusCode;                   // now you can use `statusCode` property of `NSHTTPURLResponse`

        if (statusCode != 200) {
            // Non 200 status code ... so handle HTTP error accordingly here
        }
    }

    // carry on
}];
[task resume];
Run Code Online (Sandbox Code Playgroud)

这个模式有一些稍微简单的再现,但希望它说明了这个想法:当你知道(或者已经编程确认)某个关于所指向的对象类型的东西时,你会进行转换,而你只想让编译器同时进行页面,以便您现在可以使用它.您可以使用isKindOfClass运行时检查来确认它确实是那种类型,但是转换允许您使用它.