Design protocol interfaces in Swift

RSS for tag

Discuss the WWDC22 Session Design protocol interfaces in Swift

Posts under wwdc2022-110353 tag

5 Posts

Post

Replies

Boosts

Views

Activity

Confused with type erasure when working with existential type
As per the talk, we have the following example: protocol Animal {     associatedtype CommodityType: Food     func produce() -> CommodityType } protocol Food {} struct Farm {     var animals: [any Animal]     func produceCommodities() -> [any Food] {         let produce = animals.map { animal in             // animal has type Animal             animal.produce()         }         // produce has type [Food]         return produce     } } In the video(03:51) the lecturer goes on to explain that the type of animal is any Animal but when I wrote the same code I can clearly see that the type is Animal - thus what happened to the existential ? The same goes for the return type of produce - I was expecting the type of the value to be any Food but it is Food. Anyone can explain the reason for the mismatch between what is shown in the lecture and what the compiler shows ? Using Xcode 14.2
1
0
789
Mar ’23
Unboxing protocol to concrete type in SwiftUI View
Using Swift 5.7 we're trying to use protocols for testing and mocking in our SwiftUI App. With any and some we're able to hold a heterogeneous list of protocols with self constraints which works perfectly. What we're running into now is that we can't undox the any Protocol into a concrete type for the view. Here's a basic example: protocol ItemProtocol: ObservableObject {     var id: String { get } } struct ListSection {     var id: Int     let title: String     let items: [any ItemProtocol] } protocol ViewModelProtocol: ObservableObject {     var sections: [ListSection] { get } } struct MyView<T: ViewModelProtocol>: View {   @ObservedObject     var viewModel: T     init(viewModel: T) {         self.viewModel = viewModel     }     var body: some View {         List(viewModel.sections, id: \.id) { section in             Section {                 ForEach(section.items, id: \.id) { item in                     RowView(item: item)                     // create view for some ItemProtocol                     Text("Hello Item")                 }             } header: {                 Text(section.title)             }         }     } } struct RowView<T: ItemProtocol>: View {     @ObservedObject     var item: T     init(item: T) {         self.item = item     }     var body: some View {         Text("Row View")     } } This will result in an error: Type 'any ItemProtocol' cannot conform to 'ItemProtocol' I had hoped that the any ItemProtocol would be unboxed to it's concrete type and a concrete type of View would be created.
3
1
2k
Nov ’22
Protocols and Associated Existential Types - Compiler and/or user problem?
Why is this ok …         let noCrash = controller.composer         let noCrashExtraStep = noCrash.document.title But this is not?  (Causes compiler crash — nonzero exit)         let crash = controller.composer.document.title Is this a bug in the compiler or am I missing some logic about protocols and associated types? Many thanks for any advice and also to the people who work on the Swift compiler.   Cheers Ventura / Xcode 14.1 beta 2 import SwiftUI // VIEWS @main struct CrashingApp: App { @StateObject var controller = ComposerController(composer: ConcreteComposer())     var body: some Scene {         WindowGroup {             ContentView()                 .environmentObject(controller)         }     }   } struct ContentView: View {     @EnvironmentObject var controller: ComposerController     var body: some View {         //  This line cannot be built without a crash         let crash = controller.composer.document.title                  //  If it's broken in two it works fine         let noCrash = controller.composer         let noCrashExtraStep = noCrash.document.title         Text(noCrashExtraStep)     } } // CONTROLLER class ComposerController: ObservableObject {        var composer: any ComposerProtocol     init(composer: any ComposerProtocol) {self.composer = composer } } // PROTOCOLS protocol ComposerProtocol {     associatedtype DocumentType: DocumentProtocol     var document: DocumentType {get set} } protocol DocumentProtocol {     var title: String { get set } } // CONCRETE TYPES struct ConcreteComposer: ComposerProtocol {     init() {document = ConcreteDocument()}     var document: ConcreteDocument } struct ConcreteDocument: DocumentProtocol {     var title: String = "Title" }
1
1
1.1k
Sep ’22
How to check if Data Type equals Generic Data Type and assign to Property if True?
Context I have a Generic Swift Class containing a component Property of the Generic Type. A few other Variables with different Data Types are passed through the Initializer, however, all of them are conforming to the Generic Protocol. However, I get the following Compiler Error in Line 11: 'ComponentA' is not convertible to 'C' Code protocol Component { ... } struct ComponentA: Component { ... } struct ComponentB: Component { ... } class Main&lt;C: Component&gt; { var component: C init(componentA: ComponentA, componentB: ComponentB) { // I am trying to check, whether componentA equals the Generic Data Type and assign it to the component Property if true. if case let safeComponent = componentA as C { self.component = safeComponent } } } Question How can I achieve my goal of checking whether a Data Type equals the Generic Data Type and assign it to the component Property if true?
1
0
942
Aug ’22
Swift: How to use an Array of a Protocol Type inside a SwiftUI ForEach?
Context Hey there, I am currently working with Protocols in SwiftUI and encountered a Problem. I have an Array of a Protocol Type and would like to use it to populate a SwiftUI ForEach View. However, this throws the following error: Type 'any Component' cannot conform to 'Identifiable' Code protocol Component: ObservableObject, Identifiable { var name: String { get } } struct ComponentsView: View { var body: some View { ForEach(components) { component in // Error in this Line Text(component.name) } } private var components: [any Component] { return [] } } Question How can I populate my SwiftUI ForEach View with the Array of Components?
1
1
2.6k
Aug ’22
Confused with type erasure when working with existential type
As per the talk, we have the following example: protocol Animal {     associatedtype CommodityType: Food     func produce() -> CommodityType } protocol Food {} struct Farm {     var animals: [any Animal]     func produceCommodities() -> [any Food] {         let produce = animals.map { animal in             // animal has type Animal             animal.produce()         }         // produce has type [Food]         return produce     } } In the video(03:51) the lecturer goes on to explain that the type of animal is any Animal but when I wrote the same code I can clearly see that the type is Animal - thus what happened to the existential ? The same goes for the return type of produce - I was expecting the type of the value to be any Food but it is Food. Anyone can explain the reason for the mismatch between what is shown in the lecture and what the compiler shows ? Using Xcode 14.2
Replies
1
Boosts
0
Views
789
Activity
Mar ’23
Unboxing protocol to concrete type in SwiftUI View
Using Swift 5.7 we're trying to use protocols for testing and mocking in our SwiftUI App. With any and some we're able to hold a heterogeneous list of protocols with self constraints which works perfectly. What we're running into now is that we can't undox the any Protocol into a concrete type for the view. Here's a basic example: protocol ItemProtocol: ObservableObject {     var id: String { get } } struct ListSection {     var id: Int     let title: String     let items: [any ItemProtocol] } protocol ViewModelProtocol: ObservableObject {     var sections: [ListSection] { get } } struct MyView<T: ViewModelProtocol>: View {   @ObservedObject     var viewModel: T     init(viewModel: T) {         self.viewModel = viewModel     }     var body: some View {         List(viewModel.sections, id: \.id) { section in             Section {                 ForEach(section.items, id: \.id) { item in                     RowView(item: item)                     // create view for some ItemProtocol                     Text("Hello Item")                 }             } header: {                 Text(section.title)             }         }     } } struct RowView<T: ItemProtocol>: View {     @ObservedObject     var item: T     init(item: T) {         self.item = item     }     var body: some View {         Text("Row View")     } } This will result in an error: Type 'any ItemProtocol' cannot conform to 'ItemProtocol' I had hoped that the any ItemProtocol would be unboxed to it's concrete type and a concrete type of View would be created.
Replies
3
Boosts
1
Views
2k
Activity
Nov ’22
Protocols and Associated Existential Types - Compiler and/or user problem?
Why is this ok …         let noCrash = controller.composer         let noCrashExtraStep = noCrash.document.title But this is not?  (Causes compiler crash — nonzero exit)         let crash = controller.composer.document.title Is this a bug in the compiler or am I missing some logic about protocols and associated types? Many thanks for any advice and also to the people who work on the Swift compiler.   Cheers Ventura / Xcode 14.1 beta 2 import SwiftUI // VIEWS @main struct CrashingApp: App { @StateObject var controller = ComposerController(composer: ConcreteComposer())     var body: some Scene {         WindowGroup {             ContentView()                 .environmentObject(controller)         }     }   } struct ContentView: View {     @EnvironmentObject var controller: ComposerController     var body: some View {         //  This line cannot be built without a crash         let crash = controller.composer.document.title                  //  If it's broken in two it works fine         let noCrash = controller.composer         let noCrashExtraStep = noCrash.document.title         Text(noCrashExtraStep)     } } // CONTROLLER class ComposerController: ObservableObject {        var composer: any ComposerProtocol     init(composer: any ComposerProtocol) {self.composer = composer } } // PROTOCOLS protocol ComposerProtocol {     associatedtype DocumentType: DocumentProtocol     var document: DocumentType {get set} } protocol DocumentProtocol {     var title: String { get set } } // CONCRETE TYPES struct ConcreteComposer: ComposerProtocol {     init() {document = ConcreteDocument()}     var document: ConcreteDocument } struct ConcreteDocument: DocumentProtocol {     var title: String = "Title" }
Replies
1
Boosts
1
Views
1.1k
Activity
Sep ’22
How to check if Data Type equals Generic Data Type and assign to Property if True?
Context I have a Generic Swift Class containing a component Property of the Generic Type. A few other Variables with different Data Types are passed through the Initializer, however, all of them are conforming to the Generic Protocol. However, I get the following Compiler Error in Line 11: 'ComponentA' is not convertible to 'C' Code protocol Component { ... } struct ComponentA: Component { ... } struct ComponentB: Component { ... } class Main&lt;C: Component&gt; { var component: C init(componentA: ComponentA, componentB: ComponentB) { // I am trying to check, whether componentA equals the Generic Data Type and assign it to the component Property if true. if case let safeComponent = componentA as C { self.component = safeComponent } } } Question How can I achieve my goal of checking whether a Data Type equals the Generic Data Type and assign it to the component Property if true?
Replies
1
Boosts
0
Views
942
Activity
Aug ’22
Swift: How to use an Array of a Protocol Type inside a SwiftUI ForEach?
Context Hey there, I am currently working with Protocols in SwiftUI and encountered a Problem. I have an Array of a Protocol Type and would like to use it to populate a SwiftUI ForEach View. However, this throws the following error: Type 'any Component' cannot conform to 'Identifiable' Code protocol Component: ObservableObject, Identifiable { var name: String { get } } struct ComponentsView: View { var body: some View { ForEach(components) { component in // Error in this Line Text(component.name) } } private var components: [any Component] { return [] } } Question How can I populate my SwiftUI ForEach View with the Array of Components?
Replies
1
Boosts
1
Views
2.6k
Activity
Aug ’22