zoukankan      html  css  js  c++  java
  • 【iOS开发每日小笔记(八)】instancetype类型与ID类型

    这篇文章是我的【iOS开发每日小笔记】系列中的一片,记录的是今天在开发工作中遇到的,可以用很短的文章或很小的demo演示解释出来的小心得小技巧。它们可能会给用户体验、代码效率得到一些提升,或是之前自己没有接触过的技术,很开心的学到了,放在这里得瑟一下。90%的作用是帮助自己回顾、记忆、复习。

    今天打开NSArray.h文件,偶然间发现一个类型:"instancetype"

     1 + (instancetype)array;
     2 + (instancetype)arrayWithObject:(id)anObject;
     3 + (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
     4 + (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
     5 + (instancetype)arrayWithArray:(NSArray *)array;
     6 
     7 - (instancetype)init;    /* designated initializer */
     8 - (instancetype)initWithObjects:(const id [])objects count:(NSUInteger)cnt;    /* designated initializer */
     9 
    10 - (instancetype)initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
    11 - (instancetype)initWithArray:(NSArray *)array;
    12 - (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag;

    不论是印象中还是平时自己自定义的类,都会使用"id"作为返回类型,那么这个instancetype是个什么东西,和id有什么异同呢?

    经过一番搜寻资料以及自己的测试,归纳如下:

    一:instancetype是什么?

    引用Clang:“instancetype is a contextual keyword that is only permitted in the result type of an Objective-C method”

    这说明了instancentype是一个关键字,用于Objective-C 方法的返回值。另外,instancetype的重要作用,就是这种instancetype类型的对象可以告诉编译器,该对象到底是什么类型对象。这样,编译器在编译阶段就可以通过类型判断,知道你的代码是否有问题。

    二:instancetype如何用?

    为了说明instancetype如何用,我们需要先知道一个前提:

    我们知道NSObject的创建用到的alloc init函数返回值的类型是id。但是,其实这里的id是被“优化过的”,因为编译器知道是某个特定的类去调用的alloc、init。比如:[[NSString alloc] init];那么编译器知道此时返回的对象类型应该是一个NSString。但是类方法就没有这种待遇了。下面我们就来测试一下:

    我创建了一个TestObject类。提供两种类方法。

    1 #import <Foundation/Foundation.h>
    2 
    3 @interface TestObject : NSObject
    4 
    5 + (id)testObjectWithID;
    6 
    7 + (instancetype)testObjectWithInstancetype;
    8 
    9 @end
     1 #import "TestObject.h"
     2 
     3 @implementation TestObject
     4 
     5 + (id)testObjectWithID
     6 {
     7     return [[self alloc] init];
     8 }
     9 
    10 + (instancetype)testObjectWithInstancetype
    11 {
    12     return [[self alloc] init];
    13 }
    14 
    15 @end

    接着,我分别使用这两种类方法类创建实例,并调用一个“addSubView:”的方法:

    1 UIView *view = [[UIView alloc] init];
    2 [[TestObject testObjectWithID] addSubview:view];
    3 [[TestObject testObjectWithInstancetype] addSubview:view];

    编译,提示第三行报错 No visible @interface for 'TestObject' declares the selector 'addSubview:'

    原因是编译器遇到id类型,是不会判断该类型的变量是否响应“addSubview”方法的,只在运行时才会判断。而instancetype类型,编译器就可以判断出此时这个实例是TestObject类型,而TestObject类并没有“addSubview”方法,因此会报错。

    如果单独运行:

    1     UIView *view = [[UIView alloc] init];
    2     [[TestObject testObjectWithID] addSubview:view];

    编译可以通过,但是运行就崩溃。这说明,通过instancetype类型,可以一定程度上可以提早发现误调用方法的错误。

    三:instancetype与id的不同。

    那么既然instancetype比id保险,那么是不是以后id全部用instancetype替换就好了?答案是否定的!

    因为instancetype是“is only permitted in the result type”,只能作为返回类型,不能用作函数参数等其他地方。

    我的demo很简单,供参考,地址:https://github.com/pigpigdaddy/InstancetypeDemo

    参考资料:

    http://blog.eddie.com.tw/2013/12/16/id-and-instancetype/

    http://www.iwangke.me/2013/01/06/instancetype-vs-id-for-objective-c/

    http://www.cnblogs.com/zuozeing/p/3616782.html

    http://stackoverflow.com/questions/16743494/instancetype-vs-class-name-for-singleton

  • 相关阅读:
    操作系统演进和未来趋势(附下载)
    用树莓派构建一台服务器,永久运行网站
    用 Docker 构建 MySQL 主从环境
    (一)多线程:线程概述
    网站可访问性的五个自动化测试工具
    个人对前端工程化的理解
    MongoDB安装过程中出现service MongoDB failed to start,verify that you have sufficient privileges to start
    前端开发IDE
    atom插件:js,nodejs,es6补全,高度定制化
    atom离线手动安装atom插件
  • 原文地址:https://www.cnblogs.com/pigpigDD/p/3953862.html
Copyright © 2011-2022 走看看