Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Programming language, what does it mean to start an attribute with a period

For example, in the following line of code:

DispatchQueue.global(qos: .userInitiated).async { ... }

Why does .userInitiated start with a period? Does this follow from Objective C or is it specific to Swift?

like image 634
Alec O Avatar asked Aug 07 '16 14:08

Alec O


3 Answers

Note: TLDR version at bottom

This is called Implicit member expression.

Implicit Member Expression

An implicit member expression is an abbreviated way to access a member of a type, such as an enumeration case or a type method, in a context where type inference can determine the implied type.

So as long as Swift knows the type you can often omit typing it, such as

let colour: UIColor = .red  

It is often used for enum values and static types and can be used to pass in parameters to functions like your DispatchQueue example above. Another simplified example would be:

enum Colors {
    case yellow, blue, red, green
}

So if you had this function..

func draw(withColor: Colors) {

}

you should be able to pass in the enum with the .prefix, like so

draw(withColor: .yellow)

The more verbose way in which this is a shortcut to would be:

draw(withColor: Colors.yellow)

Solution

To answer your question specifically, the .userInitiated here is actually a static property on DispatchQoS so its just a shorter way of typing DispatchQoS.userInitiated. Swift lets you shorten it becase it knows the type that is expected is of type DispatchQoS

like image 104
Scriptable Avatar answered Oct 10 '22 01:10

Scriptable


Other answers are describing the OP's case very well. But "dot syntax" is not an "enum only" feature in Swift, which is implemented in a more general way.

You can access all type members returning an instance of the type with "dot syntax" where the type can be inferred.

So, you can write something like this:

Swift 3

class MyClass {
    var value: Int
    init(value: Int) {
        self.value = value
    }
    static var `default` = MyClass(value: 0)
    private static var cache: [Int: MyClass] = [:]
    static func cachedInstance(value: Int) -> MyClass {
        if let instance = cache[value] {
            return instance
        } else {
            let instance = MyClass(value: value)
            cache[value] = instance
            return instance
        }
    }
}

var myObject: MyClass = .default //Accessing a type property
myObject = .cachedInstance(value: 2) //Accessing a type method
myObject = .init(value: 1) //Accessing an initializer

Swift 2

var myObject: MyClass = .`default` //Accessing a type property
myObject = .cachedInstance(2) //Accessing a type method
myObject = .init(value: 1) //Accessing an initializer
like image 28
OOPer Avatar answered Oct 09 '22 23:10

OOPer


That is actually an Enumeration. Enumerations can be one of multiple cases. In your example, the case is .userInitiated, which is short for QOSClass.userInitiated. The case just really stands for something, it doesn't have to have any assosiated value. Apple has this great, practical example of an enum on their site:

enum CompassPoint {
    case North
    case South
    case East
    case West
}

You access an enums members by putting a dot after the type, followed by the member name, like this: CompassPoint.North. But if the expected type is clear from context, then you can leave off the type, and just use .North.

In your example, the enum type is QoSClass. But because DispatchQueue.global(qos:) expects an enum of type QoSClass, you can leave off the type and just use .userInitiated because Swift can infer the type from context.

I said enums don't have to have an associated value, but they can. Enums with associated values can be VERY powerful, and it's one of my favorite parts of Swift. You can read much more about all of this here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html

You can also see more about how the new GCD API is implemented here: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md

like image 1
Addison Avatar answered Oct 10 '22 00:10

Addison