iOS   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ios – 方法Swizzling不起作用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想利用方法调配,但我甚至无法得到简单的例子来为我工作.我可能误解了这个概念是什么,但据我所知,它允许交换方法实现.

给定两个方法A和B,我想交换它们的实现,这样调用A就会执行B.我偶然发现了一些混合的例子(example1example2).我创建了一个带有类的新项目来测试它.@H_404_3@

class Swizzle: NSObject
{
    func method()
    {
        print("A");
    }
}

extension Swizzle
{
    override class func initialize()
    {
        struct Static
        {
            static var token: dispatch_once_t = 0;
        }

        // make sure this isn't a subclass
        if (self !== Swizzle.self)
        {
            return;
        }

        dispatch_once(&Static.token)
        {
            let originalSELEctor = SELEctor("method");
            let swizzledSELEctor = SELEctor("methodExt");

            let originalMethod = class_geTinstanceMethod(self,originalSELEctor);
            let swizzledMethod = class_geTinstanceMethod(self,swizzledSELEctor);

            print(method_getImplementation(originalMethod));
            print(method_getImplementation(swizzledMethod));

            let didAddMethod = class_addMethod(self,originalSELEctor,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));

            if DidAddMethod
            {
                class_replaceMethod(self,swizzledSELEctor,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
            }
            else
            {
                method_exchangeImplementations(originalMethod,swizzledMethod);
            }

            print(method_getImplementation(originalMethod));
            print(method_getImplementation(swizzledMethod));
        }
    }

    func methodExt()
    {
        print("B");
    }
}

然后我尝试用它来执行它@H_404_3@

var s = Swizzle();
s.method();

预期输出为“B”,但仍然打印“A”.从我的代码可以看出,我在swizzle操作之前和之后都包含了每个IMP的打印件.这些打印显示交换确实发生,但输出保持不变.@H_404_3@

输出:@H_404_3@

0x000000010251a920
0x000000010251ad40
0x000000010251ad40
0x000000010251a920
A

在让这些更改生效时,我有什么遗漏吗?@H_404_3@

Ps.目前正在使用XCode 7.0.1@H_404_3@

解决方法

问题是你的method()缺少动态指令:
class Swizzle: NSObject
{
    dynamic func method()
    {
        print("A")
    }
}

修改声明,它应该工作.@H_404_3@

在Swift中使用方法调配时,您的类/方法必须符合以下两个要求:@H_404_3@

>您的课程必须扩展NSObject
>您想要调配的函数必须具有动态属性@H_404_3@

有关为何需要此操作的完整说明,请查看Using Swift with Cocoa and Objective-C:@H_404_3@

Swift 3更新:@H_404_3@

关于GCD已经有一些变化,并且dispatch_once不再可用.为了执行相同的一次操作,我们可以将代码包含在全局静态类常量的初始化块中.@H_404_3@

Swift语言保证此代码在应用程序的生命周期内仅执行一次.@H_404_3@

class TestSwizzling : NSObject {
    dynamic func methodOne()->Int{
        return 1
    }
}

extension TestSwizzling {

    //In Objective-C you'd perform the swizzling in load(),//but this method is not permitted in Swift
    override class func initialize()
    {

        struct Inner {
            static let i: () = {

                let originalSELEctor = #SELEctor(TestSwizzling.methodOnE)
                let swizzledSELEctor = #SELEctor(TestSwizzling.methodTwo)                 
                let originalMethod = class_geTinstanceMethod(TestSwizzling.self,originalSELEctor);
                let swizzledMethod = class_geTinstanceMethod(TestSwizzling.self,swizzledSELEctor)                
                method_exchangeImplementations(originalMethod,swizzledMethod)
            }
        }
        let _ = Inner.i
    }

    func methodTwo()->Int{
        // It will not be a recursive call anymore after the swizzling
        return methodTwo()+1
    }
}

var c = TestSwizzling()
print(c.methodOne())
print(c.methodTwo())

Swift 2.2更新:@H_404_3@

我已经为新的#SELEctor属性更新了原始示例:@H_404_3@

class TestSwizzling : NSObject {
    dynamic func methodOne()->Int{
        return 1
    }
}

extension TestSwizzling {

    //In Objective-C you'd perform the swizzling in load(),//but this method is not permitted in Swift
    override class func initialize()
    {
        struct Static
        {
            static var token: dispatch_once_t = 0
        }

        // Perform this one time only
        dispatch_once(&Static.token)
        {
                let originalSELEctor = #SELEctor(TestSwizzling.methodOnE)
                let swizzledSELEctor = #SELEctor(TestSwizzling.methodTwo)                 
                let originalMethod = class_geTinstanceMethod(self,originalSELEctor);
                let swizzledMethod = class_geTinstanceMethod(self,swizzledMethod)
        }
    }

    func methodTwo()->Int{
        // It will not be a recursive call anymore after the swizzling
        return methodTwo()+1
    }
}

var c = TestSwizzling()
print(c.methodOne())
print(c.methodTwo())

如果您需要一个示例,请查看此示例项目on github.@H_404_3@

大佬总结

以上是大佬教程为你收集整理的ios – 方法Swizzling不起作用全部内容,希望文章能够帮你解决ios – 方法Swizzling不起作用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。