在NSHipter对method swizzling文章,它说:“混写应该总是在dispatch_once来完成。”为什么这是必要的,因为+加载每班只发生一次?的方法混写使用dispatch_once
7
A
回答
6
它不是必需的。 +load
保证是线程安全的并且是可重入的。见load_images
在objc-runtime-new.mm
:
/***********************************************************************
* load_images
* Process +load in the given images which are being mapped in by dyld.
* Calls ABI-agnostic code after taking ABI-specific locks.
*
* Locking: write-locks runtimeLock and loadMethodLock
**********************************************************************/
const char *
load_images(enum dyld_image_states state, uint32_t infoCount,
const struct dyld_image_info infoList[])
{
BOOL found;
recursive_mutex_lock(&loadMethodLock);
// Discover load methods
rwlock_write(&runtimeLock);
found = load_images_nolock(state, infoCount, infoList);
rwlock_unlock_write(&runtimeLock);
// Call +load methods (without runtimeLock - re-entrant)
if (found) {
call_load_methods();
}
recursive_mutex_unlock(&loadMethodLock);
return nil;
}
通知递归互斥体,即保证所有负载,同时阻止完成,call_load_methods()
将确保+负载只得到每执行+load
调用一次。
注意+load
是在特殊的存在可以在每个阶级基础,这也是为什么它的首选混写的原因之一是多种实现 - 你+load
,以及原+load
是保证调用。
奖励:这里有call_load_methods()
相关文件直接解决为什么这是线程安全的方式,它是:
/***********************************************************************
* call_load_methods
* Call all pending class and category +load methods.
* Class +load methods are called superclass-first.
* Category +load methods are not called until after the parent class's +load.
*
* This method must be RE-ENTRANT, because a +load could trigger
* more image mapping. In addition, the superclass-first ordering
* must be preserved in the face of re-entrant calls. Therefore,
* only the OUTERMOST call of this function will do anything, and
* that call will handle all loadable classes, even those generated
* while it was running.
*
* The sequence below preserves +load ordering in the face of
* image loading during a +load, and make sure that no
* +load method is forgotten because it was added during
* a +load call.
* Sequence:
* 1. Repeatedly call class +loads until there aren't any more
* 2. Call category +loads ONCE.
* 3. Run more +loads if:
* (a) there are more classes to load, OR
* (b) there are some potential category +loads that have
* still never been attempted.
* Category +loads are only run once to ensure "parent class first"
* ordering, even if a category +load triggers a new loadable class
* and a new loadable category attached to that class.
*
* Locking: loadMethodLock must be held by the caller
* All other locks must not be held.
**********************************************************************/
void call_load_methods(void)
1
我认为文章是提示说,“交叉混合应当+负载来完成”。但是你仍然可以在其他地方使用。在这种情况下,你应该在dispatch_once中调整原子性。我认为没有必要在+ load中将dispatch_once换成swizzling。
+0
让我看看代码 – dengApro 2018-01-15 07:54:47
相关问题
- 1. 使用dispatch_once
- 2. UICollectionViewCell方法混写
- 3. Destroy_all方法使用混淆
- 4. UIView的方法混写SWIFT 3
- 5. dispatch_once用法用于异步处理
- 6. 混淆“重写一个私有方法”
- 7. 使用throws子句的混淆方法
- 8. 使用一个混合的方法实例方法中的
- 9. 具有混合大小写列名的小写方法名称
- 10. 使用dispatch_once启动位置服务
- 11. dispatch_once vs static
- 12. 混淆的base64类方法的用法
- 13. 使用主要方法混淆类名
- 14. 使用方法重写
- 15. dispatch_once在超类中?
- 16. 崩溃在dispatch_once(onceToken,^ {
- 17. Swift中的dispatch_once示例
- 18. 使用Netty写高效的方法
- 19. 重写使用部分类的方法
- 20. 调用自写ruby方法的方法
- 21. 使用mod重写的无法混淆网址
- 22. 的Javascript:混淆关于函数的调用方法的使用
- 23. VueJS混入方法
- 24. 混淆方法Object.prototype.valueOf()
- 25. session.persist()方法混淆
- 26. 使用重写的子类方法的超类方法
- 27. 现有共享代理的重写/混搭方法
- 28. 方法调用的顺序混合
- 29. 用相等的方法混淆
- 30. 不使用数组编写此方法的另一种方法
大问题。没有在文章中解释,感觉像是过度杀伤。 +(无效)加载只能运行一次。我找不到任何有反例的资源。 – KirkSpaziani 2015-04-03 16:24:30
然而,我认为这是可以解释的:*再说一遍,因为调整会改变全局状态,所以我们需要在运行时采取一切预防措施。原子性就是这样的一种预防措施,就是保证代码只会执行一次,即使在不同的线程中也是如此*。这是防止竞争条件的另一个预防措施,因为我猜'load'方法不一定能保证原子性,但是使用'dispatch_once'确实是 – 2015-04-03 17:51:02