覆盖或扩展 UIColor 以支持某些协议 [英] Overriding or extending UIColor to support certain protocols

查看:75
本文介绍了覆盖或扩展 UIColor 以支持某些协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试子类化或扩展 UIColor 以支持一些协议.

I'm trying to subclass or extend UIColor to support a few protocols.

假设我的协议如下所示:

Let's say my protocol looks like this:

public protocol MyProtocol {
    init(myValue: Any) throws
}

由于某种原因,我无法实现它,我也不知道为什么.

For some reason, I'm unable to implement it, and I don't know why.

这适用于所有其他类:

class MyTestClass:SomeOtherClass, MyProtocol{
    required init(myValue: Any) throws{
        super.init(someOtherClassInitializer:Any)
    }
}

没问题.但是,如果我尝试使用 UIColor 执行此操作,则会出现错误.

No issues. But if I try to do this with UIColor, I get errors.

class MyColor:UIColor, MyProtocol{

    required init(myValue: Any) throws {
        super.init(red: 0, green: 0, blue: 0, alpha: 1)
    }
}

首先,它抱怨 required:Coder-init.好的,提供那个.致命错误很好.然后它抱怨另一个初始化.它说

first off, it complains about the required:Coder-init. Fine, provide that one. fatalError is fine. Then it complains about another init. It says

'required' 初始化器 'init(_colorLiteralRed:green:blue:alpha:)' 必须由 'UIColor' 的子类提供

'required' initializer 'init(_colorLiteralRed:green:blue:alpha:)' must be provided by subclass of 'UIColor'

奇怪的弯曲,但还好.让我们也补充一下.我点击修复",它添加了这个存根:

Weird flex, but ok. Let's add that too. I click "Fix", and it adds this stub:

@nonobjc required convenience init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {
    fatalError("init(_colorLiteralRed:green:blue:alpha:) has not been implemented")
}

然后它给了我两个错误,一个与我刚刚点击修复"的那个相同(它添加了另一个相同的初始化,一次又一次),另一个是:

Then it gives me two errors, one identical as the one I just clicked "Fix" on (which adds another identical init, and again and again), and another which says:

不支持覆盖来自扩展的非@objc 声明

Overriding non-@objc declarations from extensions is not supported

我不在扩展中,但我认为这个便利初始值设定项可能是?但是为什么我需要实施——而且不可能实施?

I'm not in an extension, but I assume this convenience initializer might be? But then why is it required for me to implement - and also impossible to implement?

我知道,你不应该继承 UIColor",但我认为如果我想让它工作,我必须这样做.这是一个奇怪的请求,所以一些背景信息;我正在使用 Apollo 库来执行 GraphQL 网络任务,它使用脚本将预期的响应转换为强类型的 swift 对象,以便我可以在代码中使用它们而无需手动反序列化它们.它运行良好.

I know, "you shouldn't subclass UIColor", but I think I have to if I want this to work. This is a weird request, so some background info; I'm using the Apollo library to perform GraphQL-network tasks, which uses a script to convert the expected response into strongly typed swift objects so I can use them in code without manually deserializing them. It's working perfectly.

大多数值是标准和原始类型,如 String、Int 等,但有时服务器会尝试向我发送一个对 Swift 来说是外部的类的对象,这些将默认为 String.这完全没问题.但我想要更花哨的.例子;值2020-01-14T10:00:00"可能作为一个名为 DateTime 的类从服务器返回,但由于DateTime"在我的项目或 Swift 中不存在,自动-生成的类将它们作为 String-value 包含,我将不得不将其视为 String.

Most of the values are the standard and primitive types, like String, Int etc., but sometimes the server tries to send me an object of a class that's foreign to Swift, and these will default to String. Which is perfectly fine. But I want more fancy. Example; the value "2020-01-14T10:00:00" might be returned as a class named DateTime from the server, but since "DateTime" doesn't exist in my project or in Swift, the auto-generated classes will contain them as a String-value, and I will have to treat it as a String.

因为我想一直使用这些自动生成的类直到视图,这意味着我必须在任何使用它的地方将它从字符串转换为日期.另一种选择是创建我自己的所有类的版本,并将所有外部类转换为我自己的,例如String->Date,这很无聊.我希望为我自动完成此操作.

Since I want to use these autogenerated classes all the way down to the view, that means I have to convert it from String to Date everywhere it's used. Another option is to create my own versions of all classes, and convert all foreign classes to my own, like String->Date, which is boring. I want this done automatically for me.

好消息是 - Apollo 允许我创建自己的自定义标量.所以有了这个DateTime -> Date"-example,我可以简单地说

The good thing is - Apollo allows me to create my own Custom Scalars. So with this "DateTime -> Date"-example, I can simply say

typealias DateTime = Date
extension DateTime, JSONDecodable, JSONEncodable{ ... }

这让 Apollo 知道有一个相应的类可以将类DateTime"的对象转换为.JSONDecodable 和 JSONEncodable 协议告诉它如何(我自己实现).使用它,自动生成的代码将生成,以便任何日期值现在都是日期时间(例如日期)而不是字符串.不错!

This lets Apollo know that theres a corresponding class that the objects of class "DateTime" can be converted to. And the protocols JSONDecodable and JSONEncodable tells it how (which I implement myself). Using this, the autogenerated code will generate so that any date-value is now a DateTime (e.g a Date) instead of a String. Nice!

所以我想,为什么不利用这个优势呢?我们还从这个 API 接收十六进制颜色.所以我们已经做到了,API 返回一个十六进制代码(#FFFFFF")作为 HexColorCode 类.默认情况下,这将变成一个 String 以便我必须在任何我想使用它的地方用十六进制初始化 UIColor.但是我现在尝试使用相同的逻辑,以便自动生成的类实际上具有我可以在任何地方直接使用的 UIColor.但是上面发生了.

So I thought, why not use this to our advantage? We also receive hex-colors from this API. So we've made it so the API returns a hex code ("#FFFFFF") as class HexColorCode. By default, this will just turn into a String so that I have to initialize a UIColor with hex everywhere I want to use it. But I'm now trying to use the same logic so that the autogenerated classes actually have a UIColor that I can use directly everywhere. But the above happens.

我假设 Date 是来自 Foundationpublic struct,具有一些自由,而 UIColor 是来自 UIKit 的 open class 继承自 NSObject,没有.但是是什么以及为什么?

I assume that Date, being a public struct from Foundation, has some freedom that UIColor, an open class from UIKit inheriting from NSObject, doesn't have. But what and why?

我认为可以创建一个包装器"对象,这样我就可以说HexColorCode"是一个具有单个 color 字段的独立类,我不得不说myView.backgroundColor = apiModel.color.color 而不仅仅是 apiModel.color.但我真的希望这能奏效..

I think it's possible to create a "wrapper"-object, so that I can say "HexColorCode" is a standalone class which has a single color-field, and I'd have to say myView.backgroundColor = apiModel.color.color instead of just apiModel.color. But I really wanted this to work..

推荐答案

我查了你的情况,也有编译器混淆的感觉.
但可能有解决方案.以下代码为我编译没有问题:

I checked your situation, and I have also the impression that the compiler gets confused.
But there might be a solution. The following code compiles for me without problems:

public protocol MyProtocol {
    init(myValue: Any) throws
}

class MyColor:UIColor {
    convenience init(myValue: Any) throws {
    self.init(red: 0, green: 0, blue: 0, alpha: 1)
    }
}

对不起:虽然这段代码可以编译,但它缺少协议.
这是(希望)正确的代码:

I am sorry: Although this code compiles, it is missing the protocol.
Here is (hopefully) the correct code:

class MyColor:UIColor, MyProtocol {
    required convenience init(myValue: Any) throws {
    self.init(red: 0, green: 0, blue: 0, alpha: 1)
    }
}

这篇关于覆盖或扩展 UIColor 以支持某些协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆