The new SwiftUI tutorial has the following code:
struct ContentView: View {
var body: some View {
Text(
'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.
Simple way to understand, like kindOf
in Objc
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/
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)
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
}
}
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
some T
solves this problemLet'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 ofT
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