5分钟带你简单实现SwiftUI面向Protocol编程

Medium上看到一篇文章感觉不错,就用我专业16级的英语翻译下,原文链接贴了估计你们也看不了,就凑合看我翻译的吧

正文

2019年苹果发布了SwiftUI。它非常强大,今年的WWDC,苹果公司也宣布了对SwiftUI进行了一系列的提升改进,然而并没有多少关于如何用SwiftUI实现面向Protocol编程的话题,

当然网上有很多的文章,我在这里用5分钟总结下,这篇文章同样适合初学者

我们最终的目标是能够用SwiftUI获取数据(假数据)并填充到List View上,我们的demo是一个显示多个足球运动员名字的列表,通常我们会把所有的东西都放到一个 Struct view对象里,现在我们试着分三层来讨论:

  • View Layer

  • Business Layer

  • Entity Layer

我们先从Entity Layer 开始,为了能把数据通过viewmodel显示到view上,我们需要一个遵循了Identifiable协议(现在是SwiftUI的一部分了)的 dummy model,这样view就能知道每一行的不同了

// The dummy model
struct Player: Identifiable {
    let id: Int
    let name: String
    let number: Int
}

现在我们来看看BL层,通常我们一般都会把所有的东西都写到一个viewmodel里,那假如我们只想让调用者知道viewmodel里的暴露出来的DataSourceaction该怎么办,这个时候我们就可以用面向协议的编程来实现

// The datasource
protocol ItemViewModelDatasource {
    var data: [Player] { get set }
}
// The action capabilities
protocol ItemViewModelAction {
    func fetchItem()
    func addPlayer(_ player: Player)
}

上面这这两个协议是我们后面用到的viewmode的datasource和action的接口,现在既然我们是在用SwiftUI编程,所以我们还需要一个遵循了ObservableObject协议的Class和一个有@Publish属性的数据源

// Base model protocol
protocol ListViewModel: ObservableObject {
    var action: ItemViewModelAction { get }
    var datasource: ItemViewModelDatasource { get set }
}

上面是ListViewModel协议,我们把它封装并且限制它只能访问actionDataSource,
现在让我们来实现完整的viewmodel class

class PlayerListViewModel: ListViewModel, ItemViewModelAction, ItemViewModelDatasource {
    
    // MARK: - Datasource
    @Published var data: [Player] = []
    
    private lazy var _datasource: ItemViewModelDatasource = {
        return self
    }()
    
    var datasource: ItemViewModelDatasource {
        get {
            return _datasource
        }
        set {
            _datasource = newValue
        }
    }
    
    // MARK: - Action
    var action: ItemViewModelAction {
        return self
    }

    func fetchItem() {
    data = [
        Player(id: 1, name: "G. Donnaruma", number: 1),
        Player(id: 2, name: "Andrea Conti", number: 12),
        Player(id: 3, name: "G. Bonaventura", number:5),
        Player(id: 1, name: "Zlatan Ibrahimovic", number: 21)
    ]
}
    
    func addPlayer(_ player: Player) {
        data.append(player)
    }
}

正如你所看到的,viewmodel需要遵循ObservedObject协议还有DataSourceaction,对了别忘了在属性data前面加上@Published修饰符,这一步是强制的,因为这个修饰符的功能就是告诉我们的view,这个属性来自于一个可观察(observable)对象然后通知监听者

struct ContentView: View where Model: ListViewModel {
    
    @ObservedObject var viewModel: Model
    
    @State var items: [String] = [
        "G. Donnarumma",
        "Andrea Conti",
        "Jack Bonaventura",
        "Zlatan Ibrahimovic"
    ]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) { item in
                    Text("Item - \(item)")
                }
            }
            .navigationBarTitle("AC Milan Player")
        }
    }
}

最后一步,我们可以像上面那样创建一个简单的view,当我们声明Struct的时候要在名字后面跟上Model类型和它支持的类型ListViewModel,这样我们就能够保证调用者传过来的modelListViewModel类型的,上面的代码我们还是用的@State items 变量来作为数据源,现在我们要把它改为用我们的viewmodelDataSource

struct ContentView: View where Model: ListViewModel {
    
    @ObservedObject var viewModel: Model
    
    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.datasource.data.indices, id:           \.self) { index in
                    Text("Item - \(self.viewModel.datasource.data[index].name)")
                }
            }
            .onAppear {
                self.viewModel.action.fetchItem()
            }
            .navigationBarTitle("AC Milan Player")
        }
    }
}

现在我们把listviewmodel里的数据做了绑定,而不是用local state,我们还做了在list.onAppear方法里去获取数据,一旦获取到数据就会得到和下图一样的效果

5分钟带你简单实现SwiftUI面向Protocol编程_第1张图片

swiftUI.png

好了就到此为止了,通过该文你应该大概了解了在SwiftUI里如何分离viewbusiness logic

喜欢的朋友可以动动小手,关注下公众号

5分钟带你简单实现SwiftUI面向Protocol编程_第2张图片

公众号

还有小程序

5分钟带你简单实现SwiftUI面向Protocol编程_第3张图片

小程序

你可能感兴趣的:(列表,编程语言,html,python,js)