在 Interface Builder 中使用泛型类作为自定义视图 [英] Use a generic class as a custom view in Interface Builder

查看:27
本文介绍了在 Interface Builder 中使用泛型类作为自定义视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的 UIButton 子类:

导入 UIKit@IBDesignable类 MyButton: UIButton {无功数组:[字符串]?}

它是 IBDesignable 并且我已经将它设置为我的故事板中一个按钮的自定义类.我想让它通用,这样数组就不必是 String 对象之一.所以,我试过这个:

导入 UIKit@IBDesignable类 MyButton: UIButton {无功数组:[T]?}

但是,我不确定现在如何将其设置为 IB 中的类.我尝试放置 MyButtonMyButton,但 Interface Builder 只是删除尖括号部分并得到以下编译错误:

Command/Applications/Xcode6-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift 失败,退出代码 254

有没有办法使用通用的自定义类,或者不支持?

解决方案

Interface Builder 通过 ObjC 运行时与您的代码对话".因此,IB 只能访问可在 ObjC 运行时中表示的代码功能.ObjC 不做泛型,所以 IB 没有办法告诉运行时使用泛型类的哪个特化.(并且 Swift 泛型类不能在没有特殊化的情况下实例化,因此尝试实例化 MyButton 而不是 MyButton 时会出错.)>

(当您破坏其他事情时,您可以识别 IB 中工作中的 ObjC 运行时:尝试在笔尖/故事板中使用带有插座/动作的纯 Swift 类会导致有关 ObjC 内省的运行时错误.让插座连接其相应的代码声明已更改或消失会导致有关 KVC 的运行时错误.等等.)

为了忽略运行时问题,并以稍微不同的方式提出来...让我们回到 IB 需要知道的事情.请记住,笔尖加载系统是在运行时实例化故事板中的任何内容.因此,即使类中采用泛型类型参数的部分不是 @IBInspectable,笔尖仍然需要知道要加载的泛型类的什么特化.因此,为了让 IB 允许您对视图使用泛型类,IB 必须有一个位置让您确定笔尖应该使用您的类的哪种专业化.它没有 - 但那会是一个很好的功能请求.

与此同时,如果您的 MyButton 类涉及一些通用存储仍然有帮助,也许您可​​以考虑让 MyButton 引用另一个包含通用存储的类.(它必须这样做,即在编译时不知道所述存储的类型,否则其他类的类型参数将不得不传播回 MyButton.)

I have a custom subclass of UIButton:

import UIKit

@IBDesignable
class MyButton: UIButton {

    var array : [String]?

}

It is IBDesignable and I have set it as the custom class for one of the buttons in my storyboard. I would like to make it generic so that the array does not have to be one of String objects. So, I tried this:

import UIKit

@IBDesignable
class MyButton<T>: UIButton {

    var array : [T]?

}

However, I am unsure how to set this as the class now in IB. I tried putting MyButton<String> or MyButton<Int>, but Interface Builder just removes the angle brackets portion and gets the following compile error:

Command /Applications/Xcode6-Beta4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254

Is there a way to use a generic custom class, or is it not supported?

解决方案

Interface Builder "talks" to your code through the ObjC runtime. As such, IB can can access only features of your code that are representable in the ObjC runtime. ObjC doesn't do generics, so there's not a way for IB to tell the runtime which specialization of your generic class to use. (And a Swift generic class can't be instantiated without a specialization, so you get an error trying to instantiate a MyButton instead of a MyButton<WhateverConcreteType>.)

(You can recognize the ObjC runtime at work in IB when you break other things: Attempting to use a pure Swift class with outlets/actions in a nib/storyboard gives runtime errors about ObjC introspection. Leaving an outlet connected whose corresponding code declaration has changed or gone away gives runtime errors about KVC. Et cetera.)

To ignore the runtime issues and put it in a slightly different way... let's go back to what IB needs to know. Remember that the nib loading system is what instantiates anything in a storyboard at runtime. So even if the parts of your class that take a generic type parameter aren't @IBInspectable, the nib still needs to know what specialization of your generic class to load. So, for IB to let you use generic classes for views, IB would have to have a place for you to identify which specialization of your class the nib should use. It doesn't — but that'd make a great feature request.

In the meantime, if it's still helpful for your MyButton class to involve some generic storage, perhaps you could look into having MyButton reference another class that includes generic storage. (It'd have to do so in such a way that the type of said storage isn't known at compile time, though — otherwise the type parameters of that other class would have to propagate back to MyButton.)

这篇关于在 Interface Builder 中使用泛型类作为自定义视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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