在我们的日常开发中我们经常会定义一些自己的子类继承一些UIKit 库中的类,那我们应该如何重写的这些初化方法呢?那我们先看看这些类有哪些初初化方法吧。(这里就用UIView为例)

- (id)init;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
- (instancetyp)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER

  我们先说说这个几个方法的执行顺序吧,init 方法我们知道它是基类NSObject 类中继承过来,应该是最基本的方法了,返回一个自己的对象。initWithCoder 这个是我们用IB初始View来调用的。-initWithFrame方法呢我们暂时先不说先往下看。
  有时候我们经常写一些的自定义东西我们想把这些东西开源出去,(当然我们很多时候都在用开源东西)。我们就想写的很完美,我们就会重载所有的初始方法,我们先来定义一个UIView 子类MyView然后重写这些方法

#import "MyView.h"

@implementation MyView{
UIView *subView;
} - (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
NSLog(@"初始化-------%@",NSStringFromSelector(_cmd));
}
return self;
} - (id)init {
self = [super init];
if (self) {
[self setup];
NSLog(@"初始化-------%@",NSStringFromSelector(_cmd));
}
return self;
} - (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
NSLog(@"初始化-------%@",NSStringFromSelector(_cmd));
}
return self;
}
- (void)setup {
subView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 20, 20)];
subView.backgroundColor = [UIColor redColor];
[self addSubview:subView];
}
@end

我们先看看在IB中创建一个view 把class 设成MyView 看看方法的调用情况:

1.1.png

我们跑下程序看看输出情况是不是像我们所说的那样:

1.2

输出结果是调用了 initWithCoder.

所以如果我们想让我们的类支持IB我们可以重写这个方法然后初始化一些东西。

下面我们来试试的手动添加的我们先用initWithFrame方法:

 #import "ViewController.h"
#import "MyView.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. MyView *myView = [[MyView alloc] initWithFrame:CGRectMake(10, 20, 100, 100)];
myView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:myView]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

我们再来运行一下看看结果:

1.3

也符合我们的预期。那我们来看看最后一种情况了,因为我们现在的项目中越来越多人采用AutoLayout了初始化的时候可能调用下init就完了。不会去调用initWithFrame方法,那我们看看我们在重写了这三个方法后调用init初始化会出现什么情况?我稍加修改一下上面的代码:

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. MyView *myView = [[MyView alloc] init];
myView.frame = CGRectMake(10, 20, 100, 100);
myView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:myView];
}

看看输出结果是什么?

1.4

奇怪了竟然先输出了initWithFrame ,然后才输出了init
为什么会这样子呢?如果你看过我的上篇文章你就应该懂了,我们可以回到最上面看看发现这个两个方法后面的都有NS_DESIGNATED_INITIALIZER这么一行字。什么意思呢?Objective-C
有指定初始化方法(designated initializer)和间接(secondary initializer)初始化方法的观念。
designated 初始化方法是提供所有的参数,secondary 初始化方法是一个或多个,并且提供一个或者更多的默认参数来调用
designated 初始化的初始化方法。由此我们可以看出init 应该是个secondary initializer 初始方法,当我们调用 [super init] 时候父类应该是去调用designated initializer 方法 initWithFrame 方法。所以我们不应该在我们的类里去重写secondary initializer 方法。如果像这样子都重写了那就会调用两遍我们的setup方法。很显然这样子是没有必要的。同时也会出现问题如果像我们上面那样的写法我们就会添加两个subView到同一个地方,这显然不是我们想要的结果所以我们应该避免这样的情况出现。这里我打下结果出来的可以自已尝试下看看:

1.5

所以当我们定义一个子类时:

  1. 不需要重载任何初始化函数(当然这个情况不太常用,我们要初始化一些我们自己东西)
  2. 重载 designated initializer(上面的我们只要重写initWithFrame
    方法即可,如果要支持IB再重写initWithCoder 就可以了,完全没有必要再去重写init 当然你可以只重写的 init
    不重写initWithFrame这样子也不会出现二次调用的问题,但这样子使用者可以使用initWithFrame方法初始化这样子就会导致一些东西会被没有初化)
  3. 定义一个新的 designated initializer
    以此类推读者可以尝试的看看UIViewController 的。(这篇文章算是上一篇文章的补充吧)。

Objective-c 中如何重写父类的初始化方法的更多相关文章

  1. C#中子类调用父类的实现方法

    这篇文章主要介绍了C#中子类调用父类的实现方法,通过实例逐步分析了类中初始化构造函数的执行顺序问题,有助于加深对C#面向对象程序设计的理解,需要的朋友可以参考下     本文实例讲述了C#中实现子类调 ...

  2. [Xcode 实际操作]九、实用进阶-(19)重写父类的绘图方法,使用图形上下文绘制自定义图形

    目录:[Swift]Xcode实际操作 本文将演示如何使用图形上下文,绘制自定义图形. 使用快捷键[Command]+[N]创建一个新的类文件. (在项目文件夹[DemoApp]上点击鼠标右键[New ...

  3. iOS学习之Object-C语言继承和初始化方法

    一.继承 1.面向对象的三大特性:封装,继承,多态.      面向对象提供了继承特性.把公共的方法和实例变量写在父类里,子类只需要写自己独有的实例变量和方法即可.继承既能保证类的完整,又能简化代码. ...

  4. java 子类重写父类的方法应注意的问题

    若想实现一个合格重写方法,而不是重载,那么必须同时满足下面的要求! A.重写规则之一:    重写方法不能比被重写方法限制有更严格的访问级别.(但是可以更广泛,比如父类方法是包访问权限,子类的重写方法 ...

  5. java在子类中,调用父类中被覆盖的方法

    在java中,子类中调用与父类同名的方法(即父类中被覆盖的方法)用super来调用即可,下面是示例: 子类父类的定义 public class b { void show() { System.out ...

  6. OC:继承、初始化方法、便利构造器

    A继承 的作用就是为了,节省代码.     继承 :子类会继承父类 里面所有的内容     思想 :凡是继承过来的实例变量和方法 都是自己的(是从父类遗传过来的)     继承的使用场景 : 当我们多 ...

  7. Swift的初始化方法

    我们在深入初始化方法之前,不妨先再想想Swift中的初始化想要达到一种怎样的目的. 其实就是安全.在Objective-C中,init方法是非常不安全的:没有人能保证init只被调用一次,也没有人保证 ...

  8. Swift开发第十篇——可变参数函数&初始化方法顺序

    本篇分为两部分: 一.Swift中的可变参数函数 二.初始化方法的顺序 一.Swift中的可变参数函数 可变参数函数指的是可以接受任意多个参数的函数,在 OC 中,拼接字符串的函数就属于可变参数函数 ...

  9. String的几种初始化方法的区别

    参考了: java中String的两种初始化方法   String a; String aa = ""; String aaa = "123"; String ...

随机推荐

  1. Oracle数据的基本操作

    一.什么是Oracle 在学习DRP系统之前,非常多次提到过Oracle,也了解过,那么Oracle是什么?今天我最终揭开了它的神奇面纱. Oracle:是一个公司.当然我在这里说的是Oracle数据 ...

  2. 【为小白菜打call】

    作为本校的竞赛生,我必须为我大OJ打call caioj,小白菜oj,顾名思义,就是为刚踏进OI的“小白菜”们准备的网站,里面包含了许多专题内容,各种模版和讲解视频 而且对于刚学习C++的同学,更有帮 ...

  3. Load和CPU利用率是如何算出来的

    相信很多人都对Linux中top命令里“load average”这一栏困惑过,到底什么是Load,Load代表了什么含义,Load高会有什么后果?“%CPU”这一栏为什么会超过100%,它是如何计算 ...

  4. C# 异步编程学习(一)

    异步 编程 可在 等待 某个 任务 完成时, 避免 线程 的 占用, 但要 想 正确地 实现 编程, 仍然 十分 伤脑筋. . NET Framework 中, 有三种 不同 的 模型 来 简化 异步 ...

  5. canvas绘制饼型图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. java 遍历list 模糊查询用

    java 遍历list 模糊查询用 /** * 筛选list * @param list 要筛选的list * @param key 筛选的key * @param <T> * @retu ...

  7. Sybase to Oracle Golden Gate

    Sybase 安装Golden Gate: 下载,然后create subdirs.并且在两端配置好mgr,设置好端口7809 创建golden gate用户ogguser,并且给它授权sa和repl ...

  8. Could not Open Install.Log File解决方法

    很多时候我们使用控制面板卸载软件会遇到could not open install.log file的报错,最近我也遇到了一次.之前遇到这样的问题,很多人都会选择直接删除软件安装目录和快捷方式等等.这 ...

  9. 用一个小的例子来说明为什么TCP采用三次握手才能保证连接成功

    关于TCP的三次握手,有很多朋友还在疑惑为什么是三次,而不是两次,LZ想了一下用一个例子来说明最好. 场景: 办公室有一名前台(服务器),若干业务员(fork出来的进程) 客户(客户端)   为什么我 ...

  10. iOS性能优化未阅文章归档

    https://www.aliyun.com/jiaocheng/349583.html https://www.2cto.com/kf/201706/648929.html 理解UIView的绘制 ...