如何将关联对象与枚举一起使用?
How to use associated objects with enums?
我有一个 ViewController,我使用关联对象向其中添加了两个新属性:一个枚举和一个字符串(字符串版本取自 here)
这是我的示例代码:
extension UIViewController {
private struct AssociatedKeys {
static var handle = "handle"
}
enum CustomStringEnum: String {
case One = "One"
case Two = "Two"
case Three = "Three"
}
var customEnum: CustomStringEnum {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as? CustomStringEnum ?? .One
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.handle, newValue.rawValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var descriptiveName: String {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as! String
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.handle,
newValue as NSString?,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let vc = UIViewController()
vc.customEnum = .Three
vc.descriptiveName = "Three"
print(vc.customEnum.rawValue) // -> This prints "One"
print(vc.descriptiveName) // -> This prints "Three"
}
}
字符串版本可以正常工作,但枚举版本不能。而且我不确定问题出在哪里。
objc_getAssociatedObject
或 objc_setAssociatedObject
有问题。 get版本好像一直都是nil,所以返回默认值One。
您在 get
函数中硬编码了 .One
。
根据您的评论,您对相关值的复杂化没有任何意义,您应该简化:
enum Numbers: String {
case One = "One"
case Two = "Two"
case Three = "Three"
// default
init() { self = .One }
static let germanNumbers = [One: "Eins", Two: "Zwei", Three: "Drei"]
var germanString: String { return Numbers.germanNumbers[self]! }
}
let num = Numbers.Three
print(num) // "Three"
print(num.rawValue) // "Three"
let defaultNum = Numbers()
print(defaultNum) // "One"
print(num.germanString) // "Drei"
print(defaultNum.germanString) // "Eins"
将您的代码更改为此
extension UIViewController {
private struct AssociatedKeys {
static var handle = "handle"
static var enumContext = "enumContext"
}
enum CustomStringEnum: String {
case One = "One"
case Two = "Two"
case Three = "Three"
}
var customEnum: CustomStringEnum {
get {
let rawvalue = objc_getAssociatedObject(self, &AssociatedKeys.enumContext)
if rawvalue == nil{
return .One
}else{
return CustomStringEnum(rawValue: rawvalue as! String)!;
}
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.enumContext, newValue.rawValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var descriptiveName: String {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as! String
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.handle,
newValue as NSString?,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
}
然后就可以了
我有一个 ViewController,我使用关联对象向其中添加了两个新属性:一个枚举和一个字符串(字符串版本取自 here)
这是我的示例代码:
extension UIViewController {
private struct AssociatedKeys {
static var handle = "handle"
}
enum CustomStringEnum: String {
case One = "One"
case Two = "Two"
case Three = "Three"
}
var customEnum: CustomStringEnum {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as? CustomStringEnum ?? .One
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.handle, newValue.rawValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var descriptiveName: String {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as! String
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.handle,
newValue as NSString?,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let vc = UIViewController()
vc.customEnum = .Three
vc.descriptiveName = "Three"
print(vc.customEnum.rawValue) // -> This prints "One"
print(vc.descriptiveName) // -> This prints "Three"
}
}
字符串版本可以正常工作,但枚举版本不能。而且我不确定问题出在哪里。
objc_getAssociatedObject
或 objc_setAssociatedObject
有问题。 get版本好像一直都是nil,所以返回默认值One。
您在 get
函数中硬编码了 .One
。
根据您的评论,您对相关值的复杂化没有任何意义,您应该简化:
enum Numbers: String {
case One = "One"
case Two = "Two"
case Three = "Three"
// default
init() { self = .One }
static let germanNumbers = [One: "Eins", Two: "Zwei", Three: "Drei"]
var germanString: String { return Numbers.germanNumbers[self]! }
}
let num = Numbers.Three
print(num) // "Three"
print(num.rawValue) // "Three"
let defaultNum = Numbers()
print(defaultNum) // "One"
print(num.germanString) // "Drei"
print(defaultNum.germanString) // "Eins"
将您的代码更改为此
extension UIViewController {
private struct AssociatedKeys {
static var handle = "handle"
static var enumContext = "enumContext"
}
enum CustomStringEnum: String {
case One = "One"
case Two = "Two"
case Three = "Three"
}
var customEnum: CustomStringEnum {
get {
let rawvalue = objc_getAssociatedObject(self, &AssociatedKeys.enumContext)
if rawvalue == nil{
return .One
}else{
return CustomStringEnum(rawValue: rawvalue as! String)!;
}
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.enumContext, newValue.rawValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var descriptiveName: String {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.handle) as! String
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.handle,
newValue as NSString?,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
}
然后就可以了