Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@bird_tomita

SwiftUIとStoryBoardの共存時期の過ごし方 for watchOS

そろそろSwiftUI使ってもいいよね?

iOS14betaも発表されて、そろそろエンタープライズアプリもiOS13対応が許される季節になってきましたが、皆様いかがお過ごしでしょうか?
と言っても、実際には過去のプロジェクトはStoryboardで沢山の画面が作られているわけで、むしろ僕の触ってるプロジェクトはそもそもObjective-Cだったりするんですが、利用現場の端末のバージョンも上がってきて、そろそろiOS13 / watchOS6の機能を使えるような空気が漂ってきました。

iOSでStoryboardとSwiftUIを混ぜる方法は こちらの記事を参考にさせていただいて非常に助かりました。

ところが開発者の少ないwatchOS関連は探してもなかなか見つからないのです。そうですね。仕方ないからメモを残しておきます。
業務の終わりのタイミングで書いてるので本当にメモです。

storyboardなInterfaceControllerからSwiftUIに遷移

既存のInterfaceControllerからSwiftUIを呼ぶには、WKHostingController を使います。
https://developer.apple.com/documentation/swiftui/wkhostingcontroller

WKHostingController は InterfaceControllerを継承しているので、今までと同じ感覚でクラスを連携させれば呼べます。

まずは、今までのWKInterfaceControllerの代わりに WKHostingControllerでコントローラーclassを作ります。

HomeViewInterfaceController.swift

import SwiftUI

class HomeViewInterfaceController : WKHostingController<HomeView> {
    override var body: HomeView {
        return HomeView()
    }
}
HomeView.swift
import SwiftUI

struct Menu: Identifiable{
    var id: Int
    var name: String

    init(id: Int, name: String){
        self.id = id
        self.name = name
    }    
}

class MenuList: ObservableObject{
    @Published var list: [Menu]

    init(){
        self.list = [
            Menu(id: 1, name:"Apple"),
            Menu(id: 2, name:"Banana"),
            Menu(id: 3, name:"Cookie"),
            Menu(id: 4, name:"Donuts")]
    }    
}

struct HomeView: View {
    @ObservedObject var mymenu: MenuList = MenuList()

    var body: some View {
        List {
            ForEach(mymenu.list){ item in
                NavigationLink(destination: SecondView(id: item.id)) {
                    Text("\(item.name)")
                }
            }
        }
    }
}

storyboardにinterfaceControllerを追加して、参照先のclassをHomeViewInterfaceController.swift に Identifierを "HomeViewInterfaceController"にします。
スクリーンショット 2020-07-09 17.43.56.png

InterfaceControllerから SwiftUIを呼び出すには

InterfaceController.m
    [self pushControllerWithName:@"HomeViewInterfaceController" context:nil];

//rootViewとして呼び出すには
    [WKInterfaceController reloadRootPageControllersWithNames:@[@"HomeViewInterfaceController"] contexts:nil orientation:WKPageOrientationVertical pageIndex:0];

といつものようにIdentifierを指定してあげればOK。

HomeからSwiftUIで定義されているSecondViewを呼び出すには、上の

                NavigationLink(destination: SecondView(id: item.id)) {
                    Text("\(item.name)")
                }

で呼び出せます。

SwiftUIからwatchKitのstoryboardのInterfaceControllerに遷移

public init(destinationName: String, @ViewBuilder label: () -> Label)

を使います。

NavigationLink(destinationName: "second") {
    Text("\(item.name)")
}

SwiftUIからstoryboard のInterfaceControllerでrootViewsをリセット

            Button(action: {
                WKInterfaceController.reloadRootControllers(withNamesAndContexts: [(name: "second", context: [:] as AnyObject )])
            }){
                Text("second")
            }

13
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What is going on with this article?