Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以使用类对象强制转换Objective-C对象吗?_Objective C_Unit Testing_Swizzling - Fatal编程技术网

可以使用类对象强制转换Objective-C对象吗?

可以使用类对象强制转换Objective-C对象吗?,objective-c,unit-testing,swizzling,Objective C,Unit Testing,Swizzling,所谓Objective-C对象,我指的是类似于MyViewController的对象和类对象MyViewController.superclass 例如,在此函数中,您将如何使用targetClass强制转换self // This code doesn't compile - (void) useOtherClassImplementation :(Class) targetClass :(SEL) targetSelector { if ([self isKindOfClass: t

所谓Objective-C对象,我指的是类似于MyViewController的对象和类对象MyViewController.superclass

例如,在此函数中,您将如何使用
targetClass
强制转换
self

// This code doesn't compile
- (void) useOtherClassImplementation :(Class) targetClass :(SEL) targetSelector {
    if ([self isKindOfClass: targetClass]) {
            ((void (*)(id, SEL))[((targetClass *) self) methodForSelector:selector])(self, selector);
        }
}
有没有一种方法可以执行类似于不编译的
((targetClass*)self)


案例研究 概述: 当ViewController出现时,将调用
ViewController.ViewDidAspect
,并运行swizzled实现。运行
ViewController.viewdide
swizzled实现后,调用原始实现。好

当原始实现运行时,
UIViewController.viewdide
,super.viewdide()调用UIViewController.viewdide。调用并运行
UIViewController.viewdideappear
的swizzled实现,在该swizzled实现中,使用
self
调用原始实现,但由于运行时
self
是ViewController而不是UIViewController,再次调用swizzled实现,从而开始递归循环

换句话说,当一个子方法(已被Swizzle)调用其super方法(也已被Swizzle)时,递归循环开始。在swizzled方法中,使用
self
调用原始实现,并且由于运行时
self
是最子类(在本例中为ViewController),super的swizzled方法再次调用子类的原始方法,因此循环重复

目标: 找到一种方法来调用swizzled类的原始实现

当运行时的
self
可能是某个子对象,并且父对象和子对象的方法在子对象方法调用父对象方法的地方都被旋转时,必须有一种方法通过使用运行时函数
class\u getInstanceMethod

已尝试但失败: 将
self
转换为另一个类,因为我无法找到如何使用类对象进行转换。要在更一般的情况下使用此swizzling代码,必须使用存储原始类的类对象,而不是显式编写类类型

ViewController.swift NSObject+Swizzling.h
下面是一个示例,说明您可以如何执行此操作:

- (void)useSuperclassImplementation:(Class)targetClass targetSelector:(SEL)targetSelector {
    if ([self isKindOfClass: targetClass] && [targetClass respondsToSelector:targetSelector]) {
        ((void (*)(id, SEL))[targetClass methodForSelector:targetSelector])(self, targetSelector);
    }
}
您可以使用
[targetClass性能选择器:targetSelector]并忽略警告

在这个答案上有一个解决方案的详细解释:


编辑:


^也是直接调用超级类的另一个选项,但这并不太安全,因为您确实需要确定目标类是超类——我需要问,为什么要这样做?对于这个问题,可能有一个更简单的解决方案。

将此表述为铸造只是让读者和你自己感到困惑。类型转换是一种纯粹的静态编译时操作<代码>目标类
,作为一个变量,当然是一个动态的、运行时的东西。在运行时,消息接收器表达式的静态类型与代码的行为无关。在那一点上,这些信息或多或少已经消失了。
[self-someMethod…]
[(AnyType*)self-someMethod…]
将编译为完全相同的代码

您是否正在寻找:

[targetClass instanceMethodForSelector:selector]
您目前拥有:

[((targetClass *) self) methodForSelector:selector]

有什么错误?@KunalShah代码实际上没有编译,但我想做一些类似于
((targetClass*)self)
你说代码不复杂。您得到的错误是什么?@KunalShah“Expected expression”紧跟在
(targetClass*)
之后,您是否试图引用目标类上的静态函数?我以前使用过此实现,但存在一个大问题。如果我同时swizzle父类和子类,并且在child function()中它调用super.function(),那么使用普通的old
self
调用子类swizzle中的子函数,并且在父类swizzle中再次调用子函数(而不是父类函数)所以这变成了递归。你有没有一个我可以看的示例项目?我有一个示例项目,但让我试着给你一个关于首先发生了什么的概述,因为这个项目有点混乱。我将在几分钟内编辑这个问题,并添加一个真实的示例
2018-04-04 17:50:43.201458-0700 TestApp[26612:6527489] Injecting selector viewDidAppear: for class UIViewController with performBefore__viewDidAppear:
2018-04-04 17:50:43.202641-0700 TestApp[26612:6527489] Injecting selector viewDidAppear: for class TestApp.ViewController with performBefore__viewDidAppear:
TestApp.ViewController is about to perform viewDidAppear:
TestApp.ViewController is about to perform viewDidAppear:
TestApp.ViewController is about to perform viewDidAppear:
(infinitely prints previous line)
- (void)useSuperclassImplementation:(Class)targetClass targetSelector:(SEL)targetSelector {
    if ([self isKindOfClass: targetClass] && [targetClass respondsToSelector:targetSelector]) {
        ((void (*)(id, SEL))[targetClass methodForSelector:targetSelector])(self, targetSelector);
    }
}
        struct objc_super superInfo = {
            .receiver = [self class],
            .super_class = targetClass
        };

        id (*objc_superAllocTyped)(struct objc_super *, SEL) = (void *)&objc_msgSendSuper;
        (*objc_superAllocTyped)(&superInfo, targetSelector);
[targetClass instanceMethodForSelector:selector]
[((targetClass *) self) methodForSelector:selector]