ios 如何创建枚举类型的 IBInspectable
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27432736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create an IBInspectable of type enum
提问by SwiftArchitect
enum
is notan Interface Builder defined runtime attribute.
The following does not show in Interface Builder's Attributes Inspector:
enum
是不接口生成器中定义的运行时属性。Interface Builder 的 Attributes Inspector 中未显示以下内容:
enum StatusShape:Int {
case Rectangle = 0
case Triangle = 1
case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle
From the documentation: You can attach the IBInspectable attribute to any property in a class declaration, class extension, or category for any type that's supported by the Interface Builder defined runtime attributes: boolean, integer or floating point number, string, localized string, rectangle, point, size, color, range, and nil.
来自文档: 您可以将 IBInspectable 属性附加到接口生成器定义的运行时属性支持的任何类型的类声明、类扩展或类别中的任何属性:布尔值、整数或浮点数、字符串、本地化字符串、矩形、点、大小、颜色、范围和零。
Q:How can I see an enum
in Interface Builder's Attributes Inspector?
问:如何enum
在 Interface Builder 的 Attributes Inspector 中看到?
回答by SwiftArchitect
Swift 3
斯威夫特 3
@IBInspectablevar shape:StatusShape = .Rectangle
merely creates a blank entry in Interface Builder:
@IBInspectablevar shape:StatusShape = .Rectangle
只是在 Interface Builder 中创建一个空白条目:
Use an adapter, which will acts as a bridgebetween Swift and Interface Builder.shapeAdapter
is inspectable from IB:
使用适配器,它将充当Swift 和 Interface Builder 之间的桥梁。shapeAdapter
可从 IB 进行检查:
// IB: use the adapter
@IBInspectable var shapeAdapter:Int {
get {
return self.shape.rawValue
}
set( shapeIndex) {
self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
}
}
Unlike the conditional compilation approach (using #if TARGET_INTERFACE_BUILDER
), the type of the shape
variable does not change with the target, potentially requiring further source code changes to cope with the shape:NSInteger
vs. shape:StatusShape
variations:
与条件编译方法(使用#if TARGET_INTERFACE_BUILDER
)不同,shape
变量的类型不会随着目标而改变,可能需要进一步更改源代码以应对shape:NSInteger
vs.shape:StatusShape
变化:
// Programmatically: use the enum
var shape:StatusShape = .Rectangle
Complete code
完整代码
@IBDesignable
class ViewController: UIViewController {
enum StatusShape:Int {
case Rectangle
case Triangle
case Circle
}
// Programmatically: use the enum
var shape:StatusShape = .Rectangle
// IB: use the adapter
@IBInspectable var shapeAdapter:Int {
get {
return self.shape.rawValue
}
set( shapeIndex) {
self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
}
}
}
? Find this solution on GitHub.
? 在GitHub 上找到此解决方案。
回答by DonVaughn
Instead of setting your inspectable enums with ints, you could also set them with strings. Although not quite as preferable as a dropdown, at least this option offers some level of readability.
除了使用整数设置可检查枚举之外,您还可以使用字符串设置它们。虽然不如下拉菜单更可取,但至少这个选项提供了一定程度的可读性。
Swift-only Option:
仅 Swift 选项:
// 1. Set up your enum
enum Shape: String {
case Rectangle = "rectangle" // lowercase to make it case-insensitive
case Triangle = "triangle"
case Circle = "circle"
}
// 2. Then set up a stored property, which will be for use in code
var shape = Shape.Rectangle // default shape
// 3. And another stored property which will only be accessible in IB (because the "unavailable" attribute prevents its use in code)
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
willSet {
// Ensure user enters a valid shape while making it lowercase.
// Ignore input if not valid.
if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
shape = newShape
}
}
}
It ispossible to also get this to work with objective-c as well, by adding an initializer to the enum. However, the compiler will only show the "unavailable" error for your IB-only properties in swift code.
这是可能的也是得到这个用Objective-C的工作,以及通过增加一个初始化的枚举。但是,编译器只会在 swift 代码中为您的 IB-only 属性显示“不可用”错误。
Swift Option with Obj-C Compatibility:
具有 Obj-C 兼容性的 Swift 选项:
@objc enum Shape: Int {
case None
case Rectangle
case Triangle
case Circle
init(named shapeName: String) {
switch shapeName.lowercased() {
case "rectangle": self = .Rectangle
case "triangle": self = .Triangle
case "circle": self = .Circle
default: self = .None
}
}
}
var shape = Shape.Rectangle // default shape
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
willSet {
if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
shape = newShape
}
}
}
回答by Jason Bobier
I can't remember the swift syntax, but this is how I solved it in obj-c
我不记得 swift 语法,但这是我在 obj-c 中解决它的方法
#if TARGET_INTERFACE_BUILDER
@property (nonatomic) IBInspectable NSInteger shape;
#else
@property (nonatomic) StatusShape shape;
#endif
回答by Ohmy
This is an old thread but useful. I have adapted my answer to swift 4.0 and Xcode 9.0 - Swift 4 has its own little issues with this problem. I am having an @IBInspectable variable with enum type and Xcode 9.0 is not happy, showing me this "Property cannot be marked @IBInspectable because its type cannot be representing in Objective-c"
这是一个旧线程,但很有用。我已经将我的答案调整为 swift 4.0 和 Xcode 9.0 - Swift 4 在这个问题上有自己的小问题。我有一个枚举类型的@IBInspectable 变量,Xcode 9.0 不满意,向我展示了这个“属性不能被标记为@IBInspectable,因为它的类型不能在Objective-c 中表示”
@Eporediese answers this problem (for swift3) in part; using a property for the storyboard but a straight enum for the rest of the code. Below is a more complete code set that gives you a property to work with in both cases.
@Eporediese 部分回答了这个问题(对于 swift3);对情节提要使用属性,但对其余代码使用直接枚举。下面是一个更完整的代码集,它为您提供了在两种情况下都可以使用的属性。
enum StatusShape: Int {
case Rectangle = 0
case Triangle = 1
case Circle = 2
}
var _shape:StatusShape = .Rectangle // this is the backing variable
#if TARGET_INTERFACE_BUILDER
@IBInspectable var shape: Int { // using backing variable as a raw int
get { return _shape.rawValue }
set {
if _shape.rawValue != newValue {
_shape.rawValue = newValue
}
}
}
#else
var shape: StatusShape { // using backing variable as a typed enum
get { return _shape }
set {
if _shape != newValue {
_shape = newValue
}
}
}
#endif
回答by Fattie
For 2020
2020年
Here's a typical full example with all of today's syntax
这是一个典型的完整示例,包含当今所有的语法
import UIKit
@IBDesignable class ClipLabels: UILabel {
enum Side: Int { case left, right }
var side: Side = .left {
didSet {
common()
}
}
@available(*, unavailable, message: "IB only")
@IBInspectable var leftRight01: Int {
get {
return self.side.rawValue
}
set(index) {
self.side = Side(rawValue: index) ?? .left
}
}
and just an example of use ...
并且只是一个使用示例......
// just an example of using it at bringup...
override init(frame: CGRect) {
super.init(frame: frame)
common()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
common()
}
private func common() {
font = .monospacedDigitSystemFont(ofSize: 12, weight: .medium)
switch side {
case .left:
textColor = .red
case .right:
textColor = .green
}
}
}
For this critical Swift/iOS QA,
对于这个关键的 Swift/iOS QA,
? the very old answer of @SwiftArchitect is perfectly correct but
? @SwiftArchitect 的旧答案是完全正确的,但是
? I've just updated it and added the critical "unavailable" thing, which is now possible in Swift.
? 我刚刚更新了它并添加了关键的“不可用”的东西,现在在 Swift 中是可能的。
回答by Eporediese
Swift 3solution based on SwiftArchitect
基于SwiftArchitect 的Swift 3解决方案
enum StatusShape: Int {
case rectangle, triangle, circle
}
var statusShape: StatusShape = .rectangle
#if TARGET_INTERFACE_BUILDER
@IBInspectable var statusShapeIB: Int {
get {
return statusShape.rawValue
}
set {
guard let statusShape = StatusShape(rawValue: newValue) else { return }
self.statusShape = statusShape
}
} //convenience var, enum not inspectable
#endif