What is the `some` keyword in Swift(UI)?

后端 未结 11 485
庸人自扰
庸人自扰 2020-12-04 04:54

The new SwiftUI tutorial has the following code:

struct ContentView: View {
    var body: some View {
        Text(         


        
相关标签:
11条回答
  • 2020-12-04 05:45

    'some' means opaque type. In SwiftUI, View is declared as a protocol

    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    public protocol View {
    
        /// The type of view representing the body of this view.
        ///
        /// When you create a custom view, Swift infers this type from your
        /// implementation of the required `body` property.
        associatedtype Body : View
    
        /// Declares the content and behavior of this view.
        var body: Self.Body { get }
    }
    

    When you create your view as Struct, you conform to the View protocol and tell that the var body will return something which will be confirming to View Protocol. Its like a generic Protocol abstraction where you don't have to Define the concrete Type.

    0 讨论(0)
  • 2020-12-04 05:46

    Simple way to understand, like kindOf in Objc

    0 讨论(0)
  • 2020-12-04 05:47

    For those who were dizzy by the subject, here a very decrypting and step by step article thanks to Vadim Bulavin.

    https://www.vadimbulavin.com/opaque-return-types-and-the-some-keyword-in-swift/

    0 讨论(0)
  • 2020-12-04 05:52

    to simplify, if you know the difference between

    var x = 5
    

    vs

    int x =5
    

    Then you'll know some. The compiler knows it, and you know it. Minimal effort for saying you comply to something without specifying the specifics (the generic types that it uses)

    0 讨论(0)
  • 2020-12-04 05:55

    The other answer does a good job of explaining the technical aspect of the new some keyword but this answer will try to easily explain why.


    Let's say I have a protocol Animal and I want to compare if two animals are siblings:

    protocol Animal {
        func isSibling(_ animal: Self) -> Bool
    }
    

    This way it only makes sense to compare if two animals are siblings if they are the same type of animal.


    Now let me just create an example of an animal just for reference

    class Dog: Animal {
        func isSibling(_ animal: Dog) -> Bool {
            return true // doesn't really matter implementation of this
        }
    }
    

    The way without some T

    Now let's say I have a function that returns an animal from a 'family'.

    func animalFromAnimalFamily() -> Animal {
        return myDog // myDog is just some random variable of type `Dog`
    }
    

    Note: this function won't actually compile. This because before the 'some' feature was added you cannot return a protocol type if the protocol uses 'Self' or generics. But let's say you can... pretending this upcasts myDog to abstract type Animal, let's see what happens

    Now the issue comes is if I try to do this:

    let animal1: Animal = animalFromAnimalFamily()
    let animal2: Animal = animalFromAnimalFamily()
    
    animal1.isSibling(animal2) // error
    

    This will throw an error.

    Why? Well the reason is, when you call animal1.isSibling(animal2) Swift doesn't know if the animals are dogs, cats, or whatever. As far as Swift knows, animal1 and animal2 could be unrelated animal species. Since we can't compare animals of different types (see above). This will error

    How some T solves this problem

    Let's rewrite the previous function:

    func animalFromAnimalFamily() -> some Animal {
        return myDog
    }
    
    let animal1 = animalFromAnimalFamily()
    let animal2 = animalFromAnimalFamily()
    
    animal1.isSibling(animal2)
    

    animal1 and animal2 are not Animal, but they are class that implements Animal.

    What this lets you do now is when you call animal1.isSibling(animal2), Swift knows that animal1 and animal2 are the same type.

    So the way I like to think about it:

    some T lets Swift know the what implementation of T is being used but the user of the class doesn't.

    (Self-promotion disclaimer) I've written a blog post that goes a little more into depth (same example as here) on this new feature

    0 讨论(0)
提交回复
热议问题