首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Swizzling UIImage.init(named:)在获取实例方法时返回nil

基础概念

UIImage 是 iOS 开发中用于表示图像的类。init(named:)UIImage 的一个便利初始化器,用于从应用程序的主 bundle 中加载图像。Swizzling 是一种运行时技术,用于替换类的方法实现。

问题描述

在使用 Swizzling 技术时,尝试获取 UIImageinit(named:) 方法的实例方法,但返回 nil

原因分析

  1. 方法不存在init(named:) 是一个便利初始化器,而不是实例方法。便利初始化器在类的元类(metaclass)中定义,而不是在实例方法列表中。
  2. Swizzling 时机不对:如果在类加载完成后再进行 Swizzling,可能会导致获取不到方法。
  3. 类已经被加载:如果类已经被加载并且初始化器已经被替换,再次尝试获取可能会失败。

解决方案

  1. 使用正确的类和元类
    • UIImage 的便利初始化器在元类中定义,因此需要获取元类的方法。
    • 使用 class_getClassMethod 而不是 class_getInstanceMethod
  • 确保在类加载前进行 Swizzling
    • 可以在 +load 方法中进行 Swizzling,因为 +load 方法会在类加载时调用。

示例代码

代码语言:txt
复制
import UIKit

extension UIImage {
    static func swizzleInitNamed() {
        guard let originalSelector = #selector(UIImage.init(named:)),
              let swizzledSelector = #selector(swizzledInitNamed(named:)) else {
            return
        }
        
        let originalMethod = class_getClassMethod(UIImage.self, originalSelector)
        let swizzledMethod = class_getClassMethod(UIImage.self, swizzledSelector)
        
        if originalMethod != nil && swizzledMethod != nil {
            method_exchangeImplementations(originalMethod!, swizzledMethod!)
        }
    }
    
    @objc private static func swizzledInitNamed(named name: String?) -> UIImage? {
        // 自定义逻辑
        print("Swizzled init(named:) called with \(name ?? "")")
        return swizzledInitNamed(named: name)
    }
}

// 在 +load 方法中进行 Swizzling
+load {
    UIImage.swizzleInitNamed()
}

参考链接

通过上述方法,可以在类加载时正确地 Swizzle UIImageinit(named:) 方法,并确保获取到正确的元类方法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

2分25秒

090.sync.Map的Swap方法

领券