网站服务器崩溃怎么办,国外网站怎么上,福步外贸论坛怎样注册,html5网站后台怎么做在 Objective-C 中#xff0c;NSObject 是绝大多数类的基类。而在 NSObject 中有两个类方法 load 和 initialize#xff0c;那这两个方法是在什么时机被调用呢#xff1f;父类、Category 的调用顺序又是怎样的呢#xff1f;本文解读一下这两个方法的区别于联系及使用场景。… 在 Objective-C 中NSObject 是绝大多数类的基类。而在 NSObject 中有两个类方法 load 和 initialize那这两个方法是在什么时机被调用呢父类、Category 的调用顺序又是怎样的呢本文解读一下这两个方法的区别于联系及使用场景。 Load load方法在这个文件被程序装载时调用。只要是在Compile Sources中出现的文件总是会被装载这与这个类是否被用到无关因此load方法总是在main函数之前调用。这个很关键也容易认知出错 调用顺序 如果一个类实现了load方法在调用这个方法前会首先调用父类的load方法。而且这个过程是自动完成的并不需要我们手动实现 父类 - 子类 - 父类的Category - 子类的Category - Main // 在 People.m(void)load {NSLog(加载Load方法: People);
}// 在 PeopleCategory.mPeople的分类(void)load {NSLog(加载Load方法: PeopleCategory);
}// 在 Student.m继承自Parent(void)load {NSLog(加载Load方法: Student);
}// 在 StudentCategory.mStudent的分类(void)load {NSLog(Load Class Childload);
}// 运行结果
2018-12-21 11:27:58.3922830800 [33801:3250290] 加载Load方法: People
2018-12-21 11:27:58.3928250800 [33801:3250290] 加载Load方法: Student
2018-12-21 11:27:58.3934000800 [33801:3250290] 加载Load方法: PeopleCategory
2018-12-21 11:27:58.3935200800 [33801:3250290] 加载Load方法: StudentCategory
2018-12-21 11:27:58.3936720800 [33801:3250290] Main开始执行 使用场景 由于load方法是线程安全的它内部使用了锁所以我们应该避免线程阻塞在load方法中。常见的使用场景是在load方法中实现Method Swizzle // In Other.m(void)load {Method originalFunc class_getInstanceMethod([self class], selector(originalFunc));Method swizzledFunc class_getInstanceMethod([self class], selector(swizzledFunc));method_exchangeImplementations(originalFunc, swizzledFunc);
} 在Child类的load方法中由于还没调用Other的load方法所以输出结果是Original Output而在main函数中输出结果自然就变成了Swizzled Output。 一般来说除了Method Swizzle别的逻辑都不应该放在load方法中实现。 initialize 这个方法在第一次给某个类发送消息时调用比如实例化一个对象并且只会调用一次。initialize方法实际上是一种惰性调用也就是说如果一个类一直没被用到那它的initialize方法也不会被调用这一点有利于节约资源。 调用顺序 // 在 People.m(void)initialize {NSLog(加载People 的initialize方法: %, [self class]);
}// 在 Student.m(void)initialize {NSLog(加载Student 的initialize方法: %, [self class]);
}// In main.m
Student *student [Student new]; // 运行结果1: 没有注释Student的initialize方法
2018-12-21 11:42:56.6942610800 [34107:3314744] 加载People 的initialize方法: People
2018-12-21 11:42:56.6944330800 [34107:3314744] 加载People 的initialize方法: Student2: 注释Student的initialize方法
2018-12-21 11:42:56.6942610800 [34107:3314744] 加载People 的initialize方法: People
2018-12-21 11:42:56.6944330800 [34107:3314744] 加载People 的initialize方法: Student 运行后发现父类的initialize方法竟然调用了两次 这是因为在创建子类对象时首先要创建父类对象所以会调用一次父类的initialize方法然后创建子类时尽管自己没有实现initialize方法但还是会调用到父类的方法。 虽然initialize方法对一个类而言只会调用一次但这里由于出现了两个类所以调用两次符合规则但不符合我们的需求。正确使用initialize方法的姿势如下 // In People.m(void)initialize {if (self [People class]) {//TODO...}
} 使用场景 initialize方法主要用来对一些不方便在编译期初始化的对象进行赋值。比如NSMutableArray这种类型的实例化依赖于runtime的消息发送所以显然无法在编译器初始化 总结 load和initialize方法都会在实例化对象之前调用以main函数为分水岭前者在main函数之前调用后者在之后调用。这两个方法会被自动调用不能手动调用它们。load只会调用一次父类没有关系而initialize方法不用显示的调用父类的方法而是自动调用即使子类没有initialize方法也会调用父类的方法load方法通常用来进行Method Swizzleinitialize方法一般用于初始化全局变量或静态变量。load和initialize方法内部使用了锁因此它们是线程安全的。实现时要尽可能保持简单避免阻塞线程不要再使用锁。转载于:https://www.cnblogs.com/fengtengfei/p/10154964.html