考慮してください:
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
Switchステートメントを使用せずに、たとえば、lefEdge
の関連値に直接アクセスするにはどうすればよいですか?
let noIdeaHowTo = leftEdge.associatedValue + 0.5
これもコンパイルされません!
これら[〜#〜] so [〜#〜]questions を見ましたが、この問題に対処する答えはありません。
上記のnoIdeaHowTo
の非コンパイル行は実際にはその1行でなければなりませんが、associated value
はどのタイプでもかまいませんが、ユーザーコードがle enum自体に「generic」getまたはrelatedValueメソッドを書き込む方法を見ることさえできません。
私はこれで終わったが、それはひどく、ケースを追加/変更するたびにコードを再訪する必要がある...
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
var associatedValue: CGFloat {
get {
switch self {
case .Horizontal(let value): return value
case .Vertical(let value): return value
}
}
}
}
ポインタはありますか?
他の人が指摘したように、これはSwift 2:
import CoreGraphics
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let min = Line.Horizontal(0.0)
let mid = Line.Horizontal(0.5)
let max = Line.Horizontal(1.0)
func doToLine(line: Line) -> CGFloat? {
if case .Horizontal(let value) = line {
return value
}
return .None
}
doToLine(min) // prints 0
doToLine(mid) // prints 0.5
doToLine(max) // prints 1
意図していないものにenum
を使用しようとしているのかもしれません。関連付けられた値にアクセスする方法は、実際にswitch
を使用することです。switch
は、enum
の可能なメンバーケースを常に処理するという考え方です。
enum
の異なるメンバーは、異なる関連する値を持つことができます(たとえば、_enum Line
_にDiagonal(CGFloat, CGFloat)
とText(String)
を含めることができます)。関連する値にアクセスする前に。たとえば、次のことを考慮してください。
_enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
case Diagonal(CGFloat, CGFloat)
case Text(String)
}
var myLine = someFunctionReturningEnumLine()
let value = myLine.associatedValue // <- type?
_
myLine
、CGFloat
、またはtwoString
sを処理している可能性があるときに、CGFloat
から関連する値を取得するにはどうすればよいでしょうか?これが、どのswitch
があるかを最初に発見するためにcase
が必要な理由です。
あなたの特定のケースでは、class
にstruct
またはLine
を使用するとよいかもしれません。これは、CGFloat
を格納し、enum
およびVertical
にHorizontal
プロパティも持つ場合があります。または、Vertical
とHorizontal
を別々のクラスとしてモデル化することもできます。たとえば、Line
をプロトコルにします。
このように、guardステートメントを使用して関連する値にアクセスできます。
enum Line {
case Horizontal(Float)
case Vertical(Float)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
guard case .Horizontal(let leftEdgeValue) = leftEdge else { fatalError() }
print(leftEdgeValue)
なぜこれが不可能なのかはすでに答えられているので、これは単なるアドバイスです。このように実装してみませんか。列挙型と構造体はどちらも値型です。
enum Orientation {
case Horizontal
case Vertical
}
struct Line {
let orientation : Orientation
let value : CGFloat
init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
}
let x = Line(.Horizontal, 20.0)
// if you want that syntax 'Line.Horizontal(0.0)' you could fake it like this
struct Line {
let orientation : Orientation
let value : CGFloat
private init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
static func Horizontal(value: CGFloat) -> Line { return Line(.Horizontal, value) }
static func Vertical(value: CGFloat) -> Line { return Line(.Vertical, value) }
}
let y = Line.Horizontal(20.0)
Swift 2を使用すると、リフレクションを使用して関連する値(読み取り専用)を取得できます。
これを簡単にするには、プロジェクトに以下のコードを追加し、EVAssociatedプロトコルで列挙型を拡張します。
public protocol EVAssociated {
}
public extension EVAssociated {
public var associated: (label:String, value: Any?) {
get {
let mirror = Mirror(reflecting: self)
if let associated = mirror.children.first {
return (associated.label!, associated.value)
}
print("WARNING: Enum option of \(self) does not have an associated value")
return ("\(self)", nil)
}
}
}
次に、次のようなコードで.asociated値にアクセスできます。
class EVReflectionTests: XCTestCase {
func testEnumAssociatedValues() {
let parameters:[EVAssociated] = [usersParameters.number(19),
usersParameters.authors_only(false)]
let y = WordPressRequestConvertible.MeLikes("XX", Dictionary(associated: parameters))
// Now just extract the label and associated values from this enum
let label = y.associated.label
let (token, param) = y.associated.value as! (String, [String:Any]?)
XCTAssertEqual("MeLikes", label, "The label of the enum should be MeLikes")
XCTAssertEqual("XX", token, "The token associated value of the enum should be XX")
XCTAssertEqual(19, param?["number"] as? Int, "The number param associated value of the enum should be 19")
XCTAssertEqual(false, param?["authors_only"] as? Bool, "The authors_only param associated value of the enum should be false")
print("\(label) = {token = \(token), params = \(param)")
}
}
// See http://github.com/evermeer/EVWordPressAPI for a full functional usage of associated values
enum WordPressRequestConvertible: EVAssociated {
case Users(String, Dictionary<String, Any>?)
case Suggest(String, Dictionary<String, Any>?)
case Me(String, Dictionary<String, Any>?)
case MeLikes(String, Dictionary<String, Any>?)
case Shortcodes(String, Dictionary<String, Any>?)
}
public enum usersParameters: EVAssociated {
case context(String)
case http_envelope(Bool)
case pretty(Bool)
case meta(String)
case fields(String)
case callback(String)
case number(Int)
case offset(Int)
case order(String)
case order_by(String)
case authors_only(Bool)
case type(String)
}
上記のコードは私のプロジェクトのものです https://github.com/evermeer/EVReflectionhttps://github.com/evermeer/EVReflection