iOS のための実装
Android より先に iOS を実装するというのは恣意的な判断です。正直なところ、最初に Android の実装を書き、次に iOS、そして Web という順番でもよかったのです。正直なところ、Android の実装を先に書いて、次に iOS、そして Web を書くこともできましたし、その 3 つを組み合わせることもできました。このチュートリアルでは、たまたま iOS を Android の前に実装しています。
プラグインの API 定義に近いので、Web を先に実装した方がいいかもしれません。もし API に手を加える必要があるなら、ウェブレイヤーで作業している間にそれを明らかにするのがはるかに簡単です。
Capacitor にプラグインを登録する
前提条件: 続ける前に、 Capacitor Custom Native iOS Code documentation を読んで、慣れ親しんでおいてください。
Xcode で npx cap open ios
を実行して、Capacitor アプリケーションの iOS プロジェクトを開きます。 App グループ ( App ターゲットの下) を右クリックし、コンテキストメニューから New Group を選択します。この新しいグループに plugins という名前を付けます。新しいグループを plugins に追加し、ScreenOrientation と名付けます。
完了すると、 /App/App/plugins/ScreenOrientation/
というパスができます。 ScreenOrientation グループを右クリックして、コンテキストメニューから New File... を選択し、以下のファイルを追加します:
ScreenOrientation.swift
ScreenOrientationPlugin.swift
次のコードを ScreenOrientationPlugin.swift
にコピーしてください:
import Foundation
import Capacitor
@objc(ScreenOrientationPlugin)
public class ScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "ScreenOrientationPlugin"
public let jsName = "ScreenOrientation"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "orientation", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "lock", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "unlock", returnType: CAPPluginReturnPromise)
]
@objc public func orientation(_ call: CAPPluginCall) {
call.resolve()
}
@objc public func lock(_ call: CAPPluginCall) {
call.resolve()
}
@objc public func unlock(_ call: CAPPluginCall) {
call.resolve();
}
}
@objc
デコレーターの利用について: これらは、Capacitor が実行時にクラスとそのメソッドを確認できるようにするために必要なものです。
現在の画面の向きを取得する
まず、現在の画面の向きを取得するタスクに取り組みましょう。 ScreenOrientation.swift
を開いてクラスを設定し、現在の向きを取得す るメソッドを記述します:
import Foundation
import UIKit
import Capacitor
public class ScreenOrientation: NSObject {
public func getCurrentOrientationType() -> String {
let currentOrientation: UIDeviceOrientation = UIDevice.current.orientation
return fromDeviceOrientationToOrientationType(currentOrientation)
}
private func fromDeviceOrientationToOrientationType(_ orientation: UIDeviceOrientation) -> String {
switch orientation {
case .landscapeLeft:
return "landscape-primary"
case .landscapeRight:
return "landscape-secondary"
case .portraitUpsideDown:
return "portrait-secondary"
default:
// Case: portrait
return "portrait-primary"
}
}
}
次に、ScreenOrientationPlugin.swift
の orientation
メソッドを配置し、実装クラスのメソッドを呼び出すようにします:
@objc(ScreenOrientationPlugin)
public class ScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "ScreenOrientationPlugin"
public let jsName = "ScreenOrientation"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "orientation", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "lock", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "unlock", returnType: CAPPluginReturnPromise)
]
private let implementation = ScreenOrientation()
@objc public func orientation(_ call: CAPPluginCall) {
let orientationType = implementation.getCurrentOrientationType()
call.resolve(["type": orientationType])
}
/* Remaining code omitted for brevity */
}
最後に、こちらの手順に従ってください:
-
カスタムのView Controllerを作成する
-
プラグインインスタンスを登録する
その後、Xcodeからアプリを実行してみましょう。実機またはiOSシミュレーターのどちらでも構いません。アプリの読み込みが完了すると、次のようなログがコンソールに表示されるはずです:
⚡️ To Native -> ScreenOrientation orientation 115962915
⚡️ TO JS {"type":"portrait-primary"}
注意: ログの正確な値は、あなたにとって異なるものになります。この例では、
115962915
はプラグインから呼び出されたメソッドに割り当てられた任意の ID です。
これで、iOS のネイティブコードと Web アプリケーションの橋渡しに成功しました! 🎉
画面の向きが変わったときの検知
iOS は、ユーザーがデバイスを回転させると、UIDevice が orientationDidChangeNotification
イベントを発生させ、NotificationCenter を通じて知らせてくれます。
load()
メソッドはこのイベントのオブザーバーを登録するのに適した場所です。同様に、オブザーバを削除するには deinit()
メソッドが適切な場所となります。
observer の登録では、プラグインの API で定義した screenOrientationChange
イベントをリスニングしているリスナーに対して、変更後の 向きを返すメソッドを提供する必要があります。変更された画面の向きを取得するために、getCurrentOrientationType()
メソッドを再利用することができます。
以下のメソッドを ScreenOrientationPlugin
クラスに追加してください:
override public func load() {
NotificationCenter.default.addObserver(
self,
selector: #selector(self.orientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc private func orientationDidChange() {
// Ignore changes in orientation if unknown, face up, or face down
if UIDevice.current.orientation.isValidInterfaceOrientation {
let orientation = implementation.getCurrentOrientationType()
notifyListeners("screenOrientationChange", data: ["type": orientation])
}
}
iOS は 3 次元の方向の変化を検出します。コードのコメントにあるように、横向きや縦向きを参照しない方向への変更は、リスナーへの通知を無視することにします。
画面の向きをロックする、ロックを解除する
When locking the Screen Orientation, we will limit the View Controller's supportedOrientations
to the requested orientation. When unlocking the Screen Orientation, we need to restore the originally
set supportOrientations
. Modify the code to save the current View Controller as well as its current supportedOrientations
. Add the following code to the ScreenOrientation
class.
private var supportedOrientations: [Int] = []
private var capViewController: CAPBridgeViewController?
public func setCapacitorViewController(_ viewController: CAPBridgeViewController) {
self.capViewController = viewController
self.supportedOrientations = viewController.supportedOrientations
}
Update the load()
function that we just added to the ScreenOrientationPlugin
class to call setCapacitorViewController()
.
override public func load() {
NotificationCenter.default.addObserver(
self,
selector: #selector(self.orientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil)
if let viewController = (self.bridge?.viewController as? CAPBridgeViewController) {
implementation.setCapacitorViewController(viewController)
}
}
Locking the Screen Orientation only works for the Capacitor View Controller, but not other View Controllers being presented (such as the one presented by Browser plugin).
To also lock presented View Controllers, this code can be added to the app's AppDelegate.swift
file:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask(rawValue: (self.window!.rootViewController as! CAPBridgeViewController).supportedInterfaceOrientations.rawValue)
}