美文网首页
SwiftUI - 跨平台

SwiftUI - 跨平台

作者: 西西的一天 | 来源:发表于2019-11-16 15:01 被阅读0次

谈到跨平台,我的内心是抗拒的,因为每个平台都有各自的特性,各自的使用场景,若仅仅为了代码复用而牺牲用户体验,岂不是本末倒置,开发产品是在服务用户还是服务程序员呢?当然也不能完全否定了,若只是复用一些基本UI组件组件确实是一个正确的选择。扯的有点远,我们回归正题。

这里所说的跨平台可不是iOS和Android,而是指iWatch,MacOS,TV。本文中仅使用iWatch App进行举例说明,同样的代码,不经过任何修改可以直接运行在iWatch上。

iPhone+iWatch.png
在这个简单的例子中,两个平台使用了同样的一个View,未经过任何的修改,示例代码请移步Github

添加Watch Target

通过File -> New -> Target -> watchOS,添加Watch App for iOS App。构建视图方式选择SwiftUI。


watch target.png

在生成的模板目录下有一个名为HostingController的文件:

import WatchKit
import Foundation
import SwiftUI

class HostingController: WKHostingController<ContentView> {
    override var body: ContentView {
        return ContentView()
    }
}

它便是Watch App的UI入口,它的body返回了一个ContentView,在ContentView在同一个目录下,只是一个普通的SwiftUI view,和我们在iOS App中看到的完全一样。运行起来看看,一个简单的Hello World显示在Watch的模拟器上。

看到这里,我们已经有了一个大概的思路,想要复用一个页面,其实也就是写一个SwiftUI的View,那么如何让一个文件被两个不同的Target使用呢?最简单的方式自然是在文件的右侧Target Memebership中同时勾选多个Target。在这里,我们来换一个思路,使用一些Swift Package。

Swift Package 复用代码

创建方式File -> New -> Swift Package


pacakge.png

创建完成后,修改一些package的配置文件Package.swift,修改其需要的各平台版本:

import PackageDescription

let package = Package(
    name: "Game",
    platforms: [.iOS(.v13), .macOS(.v10_15), .watchOS(.v6), .tvOS(.v13)],
    products: [
        .library(
            name: "Game",
            targets: ["Game"]),
    ],
    dependencies: [],
    targets: [
        .target(
            name: "Game",
            dependencies: []),
        .testTarget(
            name: "GameTests",
            dependencies: ["Game"]),
    ]
)

然后将需要复用的代码移至该package的Sources下,这里,我们放入了一个View和它的ViewModel

import SwiftUI

public struct BullsEyeContentView: View {
    @ObservedObject private var game = BullsEyeGame()

    @State private var currentValue = 50.0
    @State private var showAlert = false

    private var alpha: Double {
        abs(Double(game.targetValue) - currentValue) / 100.0
    }

    public init() {}
    
    public var body: some View {
        VStack {
            Text("Aim to: \(game.targetValue)")
            HStack {
                Text("0")
                Slider(value: $currentValue, in: 1.0...100.0, step: 1.0)
                    .background(Color.blue)
                    .opacity(alpha)
                Text("100")
            }
            .padding(.horizontal)
            Button(action: {
                self.showAlert = true
                self.game.checkGuess(Int(self.currentValue))
            }) {
                Text("Hit Me!")
            }.alert(isPresented: $showAlert) {
                Alert(title: Text("Your Score"), message: Text(String(game.scoreRound)),
                      dismissButton: .default(Text("OK"), action: {
                        self.game.startNewRound()
                        self.currentValue = 50.0
                      }))
            }
            .padding()
            HStack {
                Text("Total: \(game.scoreTotal)")
                Text("Round: \(game.round)")
            }
        }
    }
}

需要注意的,添加访问修饰符public。那么如何让App和Watch可使用pacakge中的代码呢?和引用一个系统的Framwork一样,在该Target的General配置页中的Frameworks, Libraries, and Embedded Content中添加该Target。

大功告成,这一节的内容非常简单,并不是在说WatchApp该如何开发,只是在聊聊使用SwiftUI开发WatchApp UI的方式,以及如何通过Swfit Package来复用代码。各位看官,我们下周继续,周末愉快。

相关文章

网友评论

      本文标题:SwiftUI - 跨平台

      本文链接:https://www.haomeiwen.com/subject/fojyictx.html