SwiftUI - How do I change a synchronous value using an asynchronous operation inside a List Cell

陌路散爱 提交于 2020-12-15 05:14:26

问题


I have this previous question properly answer. That case is of an image somewhere in the interface.

I have another variation of the same problem but now the image is inside a List Cell.

That image shows a padlock that must only show if a particular inapp purchase was not purchased, on SwiftUI.

Something like

  Image(systemName: "lock.circle.fill")
    .renderingMode(.template)
    .foregroundColor(.white)
    .font(symbolFont)
    .opacity(wasPurchased(item: item))

But as far as I see wasPurchased must be a synchronous function, right?

Something like

func wasPurchased(item: item) -> Bool {
    return check(item:item) ? true : false
}

But, such checks normally happen asynchronously, over the network, and the function, as I see, must have a signature like

func wasPurchased(item: item, runOnFinishChecking:(Bool)->()) {

That list is populated from Core Data, like this

@FetchRequest(fetchRequest: Expressao.getAllItemsRequest())
private var allItems: FetchedResults<Expressao>


var body: some View {
  List {
    ForEach(allItems, id: \.self) { item in
      HStack {
        Text(item.term)
          .font(fontItems)
          .foregroundColor(.white)

        Image(systemName: "lock.circle.fill")
          .renderingMode(.template)
          .foregroundColor(.white)
          .font(symbolFont)
          .opacity(wasPurchased(item: item))
      }
    }
   }
  }

I don't see how I can use something asynchronous to control the opacity of such element when the whole thing is an array.

How do I do that?


回答1:


Just separate your row content into standalone view and apply approach from previous post.

var body: some View {
  List {
    ForEach(allItems, id: \.self) {
       ExpressaoRowView(item: $0)
    }
  }
}

...

struct ExpressaoRowView: View {
   @ObservedObject var item: Expressao
   
   @State private var locked = true
   
   var body: some View {
      HStack {
        Text(item.term)
          .font(fontItems)
          .foregroundColor(.white)

        Image(systemName: "lock.circle.fill")
          .renderingMode(.template)
          .foregroundColor(.white)
          .font(symbolFont)
          .opacity(self.locked ? 1 : 0)
      }
      .onAppear {
        self.wasPurchased(self.item) { purchased in
          DispatchQueue.main.async {
             self.locked = !purchased
          }
       }
    }
   }
}

Note: you can even keep wasPurchased checker somewhere outside (in parent or in some helper) and inject into ExpressaoRowView as a property



来源:https://stackoverflow.com/questions/64710021/swiftui-how-do-i-change-a-synchronous-value-using-an-asynchronous-operation-in

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!