基于 iOS 版本的条件子类化

Posted

技术标签:

【中文标题】基于 iOS 版本的条件子类化【英文标题】:Conditional subclassing based on iOS version 【发布时间】:2016-06-04 18:46:58 【问题描述】:

这个问题可能有点奇怪,有没有办法根据 ios 版本有条件地进行子类化,本质上是:

if(iOS version >= 9) 
   @interface CDVWKWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol, WKScriptMessageHandler, WKNavigationDelegate>
 else if(iOS version = 8) 
   @interface CDVWKWebViewEngine : CDVPlugin <WKScriptMessageHandler, WKNavigationDelegate>

我有 iOS Cordova WkWebView Engine plugin,想退回到 iOS 8 下的 UIWebView(忽略 iOS 8 上的插件)。

我发现有条件地使用这个插件是相当棘手的,因为一旦它继承了 UIWebView 默认插件,它就深深植根于项目中。

【问题讨论】:

你可以做到,但你最好拥有一个包含两个实现的子类,并让每个函数调用你想要使用的正确函数。也许你可以使用组合来代替继承。 【参考方案1】:

有针对不同版本定义的预处理器宏

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
// code to compile for iOS 9 or greater
#else
// code to compile for les than iOS 9
#endif

如果您想在运行时做出决定,可以使用-systemVersion (UIDevice)。

当然,在运行时编译一个不同的类是不可能的,就像你在 Q 中想要的那样。有两种方法来处理它:

在运行时创建一个类。这样做,您需要将方法中的整个代码编译并放在一起。

在运行时从已编译的类中选择正确的类(或 Brandon 建议的代码片段)。

有不同的方法可以做到这一点。如果它适合您的结构,您可以拥有一个基类和两个私有子类,并在您决定在基类内创建实例时,决定创建和交付哪个子类的哪个实例。

【讨论】:

这是用于运行时应用程序还是使用的 SDK?我正在使用上面的代码,但它似乎在 iOS 8 设备上运行适用于 iOS 9 的代码 使用了 SDK。 “运行时应用程序”是什么意思?当然,您无法根据应用程序运行的 iOS 版本、编译后的天数、数年来决定编译什么。您想对运行时做出决定吗?我可以补充一下。 是的,这样会更好,因为我只能分发一个应用程序,iOS 8 和 wkWebView 下的 webkit 存在一些问题。最好是在运行时而不是编译时决定使用哪个类【参考方案2】:

您不能在运行时定义一个类遵循哪些协议,因为这是一个编译时决定。 (实际上,一种使用低级 C API 的方法,例如 class_addProtocol,但这里不需要。除非你真的知道你在做什么,否则你不应该像那样搞乱运行时。 )

协议主要是向编译器提示您将支持哪些方法。它允许编译器发出某些警告,例如缺少所需协议方法的实现。

在您的情况下,只需定义您需要的所有协议(“联合”;在您的情况下:WKWebView 和 UIWebView 协议)并实现这些方法。然后根据需要在运行时配置您的对象。这意味着,像viewDidLoad 这样的地方,决定您是否需要WKWebViewUIWebView 并相应地进行设置。或者,如果您使用的是 XIB,您可能希望使用两种不同的 XIB(一种使用 WKWebView,另一种使用 UIWebView)并在运行时决定加载哪个。

【讨论】:

class_addProtocol() 如何提供帮助?协议是编译器的输入提示。此外,它们强制执行声明的方法的实现。在运行时添加协议不会这样做,因此您的输入完全没有意义。他必须添加方法,而不是协议。 @AminNegm-Awad:呃,这不是我写的吗?为了完整起见,我只是提到了class_addProtocol(也许应该避免这样做以避免混淆):有一种方法可以在运行时添加/删除协议,但你不应该也不需要这样做。您可以使用-[AClass conformsToProtocol:@protocol(Foo)] 检查一个类是否符合协议,因此理论上,添加协议也可以在运行时产生影响,但我根本不知道在 Cocoa 中使用了该协议。 但我的意思是:添加所有使用的协议,实现所有需要的方法,在运行时配置。 当然,添加协议可以有所作为。这就是这个函数存在的原因。但是添加协议并不能实现实现,这对他来说是必要的。 @AminNegm-Awad:我确实写过他需要实现这些方法,不是吗?我真的不明白你在批评什么,我的措辞应该不同/更详细吗? 我只是想说,即使它是你 A 的一部分,是否可以在运行时添加协议也无关紧要。您必须做的任务是为声明的方法添加实现。所以你答案的前两段至少是多余的。

以上是关于基于 iOS 版本的条件子类化的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 iOS 中基于 NSString 值动态创建 NSManagedObject 子类

基于Docker容器化快速搭建Halo个人博客并配置https服务

Tikhonov基于Tikhonov正则化的图像超分辨率重建

子类化 UIAlertController

NSCell 子类化:绘制 NSProgressIndicator?

UICollectionViewFlowLayout 与子类化 UICollectionViewLayout