Sharing the Code

Programming stuff that might be useful to others

How to do X in Swift?

When writing Swift code you’re bound to come across things that you might have been used to doing in Objective-C but haven’t a clue how to do in Swift. Below is a collection of gotchas I came across.

Key Value Observing

Prefix dynamic to the properties you want to observe. These properties have to use Objective-C types.

dynamic var someProperty:NSString

Options

The code for creating options is quite convoluted. Luckily this blog provides a utility for generating it. If you want to write something like if options & .AnOption you will need the options to extend BooleanType and implement the property boolValue:

var boolValue: Bool { return value != 0 }

The utility mentioned above creates code that is compatible with XCode 6.1. Below shows you the differences between the code for XCode 6.0 and 6.1:

XCode 6.0:

struct ObjectOperations : RawOptionSetType, BooleanType {
    private var value: UInt = 0
    init (_ value:UInt) { self.value = value }
    // RawRepresentable
    func toRaw() -> UInt { return self.value }
    static func fromRaw(raw: UInt) -> ObjectOperations? { return self(raw) }
    // RawOptionSetType
    static func fromMask(mask: UInt) -> ObjectOperations { return self(mask) }
    static func convertFromNilLiteral() -> ObjectOperations { return self(0) }
    // BitwiseOperationsType
    static var allZeros: ObjectOperations { return .None }
    // BooleanType
    var boolValue: Bool { return value != 0 }

    static var None: ObjectOperations { return self(0) }
    static var Index: ObjectOperations { return self(1 << 0) }
    static var Show: ObjectOperations { return self(1 << 1) }
    static var Create: ObjectOperations { return self(1 << 2) }
    static var Update: ObjectOperations { return self(1 << 3) }
    static var Destroy: ObjectOperations { return self(1 << 4) }
    static var Any: ObjectOperations { return .Index | .Show | .Create | .Update | .Destroy }
}

XCode 6.1:

struct ObjectOperations : RawOptionSetType, BooleanType {
    typealias RawValue = UInt
    private var value: UInt = 0
    init(_ value: UInt) { self.value = value }
    init(rawValue value: UInt) { self.value = value }
    init(nilLiteral: ()) { self.value = 0 }
    // RawRepresentable
    var rawValue: UInt { return self.value }
    // RawOptionSetType
    static func fromMask(raw: UInt) -> ObjectOperations { return self(raw) }
    static func convertFromNilLiteral() -> ObjectOperations { return self(0) }
    // BitwiseOperationsType
    static var allZeros: ObjectOperations { return self(0) }
    // BooleanType
    var boolValue: Bool { return value != 0 }

    static var None: ObjectOperations { return self(0) }
    static var Index: ObjectOperations { return ObjectOperations(1 << 0) }
    static var Show: ObjectOperations { return ObjectOperations(1 << 1) }
    static var Create: ObjectOperations { return ObjectOperations(1 << 2) }
    static var Update: ObjectOperations { return ObjectOperations(1 << 3) }
    static var Destroy: ObjectOperations { return ObjectOperations(1 << 4) }
    static var Any: ObjectOperations { return .Index | .Show | .Create | .Update | .Destroy }
}

Converting enums to integers

It’s fairly common to have to convert enums to integers when working with web services or persisting to disk. First the enum needs to extend Int and then you define the value of the first enum and the others increment from there, i.e. below ObjectiveC would have a value of 2.

enum Language: Int {
  case Swift = 1, ObjectiveC
}

If you want to access the integer value, you do the following depending on the version of XCode you are using:

XCode 6.0:

var integerValue = langauge.toRaw()

XCode 6.1:

var integerValue = langauge.rawValue

And if you want to create an enum from an integer:

XCode 6.0:

var language = Language.fromRaw(1)

XCode 6.1:

var language = Language(rawValue:1)

This returns an optional, as not all integers are valid enum values.

You can also get the value as a String by implementing Printable e.g.

enum Language: Int, Printable {
  case Swift = 1, ObjectiveC

  var description: String {
    switch self {
    case .Swift:
      return "Swift"
    case .ObjectiveC:
      return "Objective-C"
    }
  }
}

NSClassFromString

If you want to dynamically create an instance from a class name you can use:

let clazz = NSClassFromString("SomeClass")
let object = clazz()

But you will need to prefix the class with @objc e.g.

@objc(SomeClass) class SomeClass{
...
}

Comments are closed