Issue #763  
I usually break down a big struct into smaller views and extensions. For example I have a ClipboardCell that has a lot of onReceive so I want to move these to another component.
One way to do that is to extend ClipboardCell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 struct  ClipboardCell : View      let  isSelected: Bool      @State  var  showsPreview: Bool      @State  var  showsViewRaw: Bool      let  onCopy: () -> Void      let  onDelete: () -> Void  } extension  ClipboardCell      func  onReceiveKeyboard () View  {         self .onReceive(             NotificationCenter .default                  .publisher(for : .didKeyboardCopyItem)                 .receive(on: RunLoop .main),             perform: { note in                  onCopy()             }         )     } } 
but then when we want to use this, we get some View has no member onReceiveKeyboard as self after some Swift modifier becomes some View, unless we call onReceiveKeyboard first
1 2 3 4 5 6 7 struct  ClipboardCell : View      var  body: some View  {         self         .padding()        .onReceiveKeyboard()     } } 
Use ViewModifier The SwiftUI is to use ViewModifier where we can inject Binding and functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 struct  ClipboardCellOnKeyboardModifier : ViewModifier      let  isSelected: Bool      @Binding  var  showsPreview: Bool      @Binding  var  showsViewRaw: Bool      let  onCopy: () -> Void      let  onDelete: () -> Void      func  body (content: Content) View  {         content.onReceive(             NotificationCenter .default                  .publisher(for : .didKeyboardCopyItem)                 .receive(on: RunLoop .main),             perform: { _  in                  guard  isSelected else  { return  }                 onCopy()             }         )     } } ` 
Then we can consume it and pass parameters
1 2 3 4 5 6 7 8 9 10 11 12 struct  ClipboardCell : View      var  body: some View  {         self         .padding()        .modifier(            ClipboardCellOnKeyboardModifier (                showsPreview: Binding <Bool >(get : {}, set : {}) ,                showsViewRaw: Binding <Bool >(get : {}, set : {})             )        )     } } 
Pass State and Binding For now SwiftUI seems to have a bug that ViewModifier does not listen to onReceive, we can extend generic View and pass parameters instead
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 extension  View      func  onClipboardCellReceiveKeyboard (          isSelected: Bool,         showsPreview: Binding<Bool>,         showsViewRaw: Binding<Bool>,         onCopy: ()  Void ,        onDelete: () -> Void      ) -> some View  {         self .onReceive(             NotificationCenter .default                  .publisher(for : .didKeyboardCopyItem)                 .receive(on: RunLoop .main),             perform: { _  in                  guard  isSelected else  { return  }                 onCopy()             }         ) 
Use ObservableObject Another way is to use an ObservableObject and encapsulate logic and state in there, and share this across views that want to consume this set of data, just like a ViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import  SwiftUIfinal  class  ItemsHolder : ObservableObject      @Published  var  items: [ClipboardItem ] = []     @Published  var  selectedItems = Set <ClipboardItem >()     @Published  var  agos: [UUID : String ] = [:]     func  updateAgos ()          agos.removeAll()         for  item in  items {             agos[item.id] = Formattes .ago(date: item.createdAt)         }     }     func  update (items: [ClipboardItem])          self .items = items             .sorted(by: { $0 .createdAt > $1 .createdAt })         updateAgos()     } } struct  ClipboardCell : View      @StateObject  var  itemsHolder = ItemsHolder ()     var  body: some View  {         list.onReceive(             NotificationCenter .default                  .publisher(for : .didKeyboardCopyItem)                 .receive(on: RunLoop .main),             perform: { note in                  itemsHolder.onCopy()             }         )     } } 
Updated at  2021-01-29 12:51:52