- 投稿日:2020-09-17T23:36:59+09:00
Ionic Native Pluginを自作する
Ionic Cordova Pluginの開発
携わっているプロジェクトで使用することになったのでメモがてら
Cordova Pluginの作成
ディレクトリ作成
プラグイン開発は以下のフォルダ構成で行います。
フォルダ構成./custom_plugins └── cordova-plugin-helloworld ・・・プラグイン名 ├── package.json ├── plugin.xml ├── src │ ├── android │ │ └── HelloWorld.java ・・・ AndroidのNativeコード │ └── ios │ └── HelloWorld.swift ・・・ iOSのNativeコード └── www └── helloworld.js ・・・ Web側実行コードpackage.jsonの作成
package.jsonの内容は以下の通りです。
package.json{ "name": "cordova-plugin-helloworld", "version": "1.0.0", "cordova": { "id": "cordova-plugin-helloworld", "platforms": [ "android", "ios" ] } }plugin.xmlの作成
plguin.xml<?xml version="1.0" encoding="UTF-8"?> <!-- id: プラグインの識別子、version: プラグインのバージョン --> <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-helloworld" version="1.0.0"> <!-- プラグイン名 --> <name>HelloWorld</name> <!-- プラグインの説明 --> <description>HelloWorld!!!</description> <!-- ライセンス --> <license>HogeLicense</license> <!-- プラグインがサポートするCordovaのバージョン --> <engines> <engine name="cordova-android" version=">5.0.0"/> </engines> <!-- JSの場所指定。name: モジュール名 --> <js-module src="www/helloworld.js" name="HelloWorld"> <clobbers target="HelloWorld"/> </js-module> <!-- iOS用の設定 --> <platform name="ios"> <config-file target="config.xml" parent="/*"> <!-- Swift Class名 --> <feature name="HelloWorld"> <!-- Valueが@objc(HelloWorld) --> <param name="ios-package" value="HelloWorld" onload="true" /> </feature> </config-file> <!-- Swiftを使用する --> <source-file src="src/ios/HelloWorld.swift" /> </platform> <!-- Android用の設定 --> <platform name="android"> <!-- Androidのconfig.xmlはここ→project/platform/android/res/xml/config.xmlにあるのでそこに反映するように --> <config-file target="res/xml/config.xml" parent="/*"> <!-- Cordovaはfeatureタグをみて、どのプラグインが有効か見る。以下の情報が上記のファイルに追加される。 --> <feature name="helloworld"> <param name="android-package" value="plugin.helloworld.HelloWorld"/> </feature> </config-file> <!-- Javaのソースファイル。 target-dir: ファイルがコンパイルされるべき場所 --> <!-- 以下だとproject/platform/android/src/plugin/helloworld/以下になる --> <source-file src="src/android/HelloWorld.java" target-dir="src/plugin/helloworld/"/> </platform> </plugin>helloworld.jsの作成
helloworld.jsvar exec = require("cordova/exec"); module.exports = { echo: function (name, successCallback, errorCallback) { // 第1引数: 成功時に呼び出す関数 // 第2引数: エラー時に呼び出す関数 // 第3引数: プラグインの名前(plugin.xmlのfeatureのnameに設定したもの) // 第4引数: HelloWorld.javaの第1引数に渡る名前 // 第5引数: HelloWorld.javaの第2引数に渡る値 exec(successCallback, errorCallback, "helloworld", "echo", [name]); }, };HelloWorld.javaの作成(Android Native)
HelloWorld.java// plguin.xml -> feature -> param -> value で指定した物 package plugin.helloworld; import org.apache.cordova.*; import org.json.JSONArray; import org.json.JSONException; public class HelloWorld extends CordovaPlugin { @Override public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException { if (action.equals("echo")) { String name = data.getString(0); String message = "Hello, World !!! " + "Hello, " + name; callbackContext.success(message); return true; } else { return false; } } }HelloWorld.swiftの作成(iOS Native)
HelloWorld.swiftimport Foundation import UIKit @objc(HelloWorld) class HelloWorld: CDVPlugin { // JavaScriptに公開する関数名を記述 @objc(echo:) func echo(command: CDVInvokedUrlCommand) { let name = command.arguments.first as! String let message = "Hello, World !!! " + "Hello, " + name; // 返却するレスポンスを作成 let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: message) // コールバック形式でレスポンスを返却 self.commandDelegate!.send(result, callbackId: command.callbackId) } }一旦作成したPluginを使ってみる
空のIonicプロジェクトを作成し、上記で作成たプラグインをaddする。
$ ionic start plugin-test blank $ cd plugin-test今回は以下のようにプロジェクト内にカスタムプラグインのファイルを配置する。
prugin-test └── custom_plugins │ └── cordova-plugin-helloworld ・・・今回作成したプラグイン └── node_modules └── src ・ ・ ・プラグインの追加
$ ionic cordova plugin add ./custom_plugins/cordova-plugin-helloworld
アプリ側にプラグインの実行処理を実装
home.page.tsimport { Component } from "@angular/core"; import { Platform } from "@ionic/angular"; ・・・ 追加 declare var HelloWorld: any; ・・・ 追加 Ionic Nativeに対応していない場合はこの定義が必要 @Component({ selector: "app-home", templateUrl: "home.page.html", styleUrls: ["home.page.scss"], }) export class HomePage { ・・・以下全て追加 constructor(public platform: Platform) { this.platform.ready().then(() => { HelloWorld.echo("MyName", this.successCallback, this.errorCallback); }); } // 成功時の処理 successCallback(message) { alert(message); } // エラー時の処理 errorCallback() { alert("hello error"); } }Platformの追加と実装
Platformの追加
$ ionic cordova platform add android $ ionic cordova platform add ios実行
$ ionic cordova run android $ ionic cordova run ios結果
Android
iOS
Ionic native pluginの作成
準備
先ほど作成したCordova pluginをIonic native pluginとして使えるようにします。まず、最初にnative pluginに必要なコードをhttps://github.com/ionic-team/ionic-nativeからクローンします。ディレクトリはどこでも良いのすが、
$ cd todo $ git clone https://github.com/ionic-team/ionic-native.gitionic-native/src/@ionic-native/pluginsの下には既存のIonic native pluginのソースコードが置いてあります。ビルドするときに邪魔になるので一旦pluginsの下を全て削除します。
$ rm -rf ionic-native/src/@ionic-native/plugins/*Native Plugin用のファイルの生成
$ cd ionic-native $ npm install $ gulp plugin:create -n HelloWorldPlugingulpが未インストールの場合はインストール
npm install -g gulp正常に終了すると以下のファイルが生成されます。
src/@ionic-native/plugins/hello-world-plugin/index.tsプラグインの定義部分を以下のように変更します。
src/@ionic-native/plugins/hello-world-plugin/index.ts@Plugin({ pluginName: 'HelloWorldPlugin', plugin: 'cordova-plugin-helloworld', // npm package name, example: cordova-plugin-camera pluginRef: 'HelloWorldPlugin', // the variable reference to call the plugin, example: navigator.geolocation repo: '', // the github repository URL for the plugin install: '', // OPTIONAL install command, in case the plugin requires variables installVariables: [], // OPTIONAL the plugin requires variables platforms: ['Android', 'iOS'], // Array of platforms supported, example: ['Android', 'iOS'] }) /** ・pluginName:コマンド実行時に自動で追加されます。今回作成するパッケージ名になります。実際には、wewi-cordova-pluginで読み出します。 ・plugin:前回作成したcordova pluginのidです。 ・pluginRef:cordova pluginの呼び出し名です。 ・platforms:利用するplatformを配列で指定。 */次にクラス内にメソッドを追加します。今回作成したメソッドは、helloだけなので下記の様になります。複数ある場合は、同じ様に追加して行きます。
src/@ionic-native/plugins/hello-world-plugin/index.ts@Injectable() export class HelloWorldPlugin extends IonicNativePlugin { /** * This function does something * @param arg1 {string} Some param to configure something * @param arg2 {number} Another param to configure something * @return {Promise<any>} Returns a promise that resolves when something happens */ @Cordova() echo(arg1: string): Promise<any> { return; // We add return; here to avoid any IDE / Compiler errors } }最後にlintでエラーが発生するので、不要なimportは削除する。今回のimport文は、下記の通りとになります。
import { Injectable } from '@angular/core'; import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';Native Pluginのビルド
index.tsの編集が完了したら、次にbuildしてnpmでインストール出来る形にします。
$ npm run buildコマンドが正常終了すると、下記のディレクトリが出来ているはずです。
dist/@ionic-native/wewi-cordova-plugin
├── index.d.ts
├── index.js
├── index.js.map
├── index.metadata.json
└── package.json
Native Pluginのインストール
作成したNative Pluginをインストールします。単純にプロジェクトのnode_modules/@ionic-nativeの下にコピーしても使えますが、アプリのビルドなどをしていると消えることがあるので、インストールした方が良いようです。インストールはプロジェクトのトップで以下のコマンドを実行します。
※私の環境では、上記でpackage.jsonが作成されなかったので、コピーして使用しました。$ npm install --save 任意のフォルダ/ionic-native/dist/\@ionic-native/hello-world-plugin呼び出しコードを修正
home.module.tsimport { NgModule } from "@angular/core"; import { CommonModule } from "@angular/common"; import { IonicModule } from "@ionic/angular"; import { FormsModule } from "@angular/forms"; import { HomePage } from "./home.page"; import { HelloWorldPlugin } from "@ionic-native/hello-world-plugin/ngx"; ・・・追加 import { HomePageRoutingModule } from "./home-routing.module"; @NgModule({ imports: [CommonModule, FormsModule, IonicModule, HomePageRoutingModule], declarations: [HomePage], providers: [HelloWorldPlugin], ・・・追加 }) export class HomePageModule {}home.page.tsimport { Component } from "@angular/core"; import { Platform } from "@ionic/angular"; import { HelloWorldPlugin } from "@ionic-native/hello-world-plugin/ngx"; ・・・追加 // declare var HelloWorld: any; ・・・削除 @Component({ selector: "app-home", templateUrl: "home.page.html", styleUrls: ["home.page.scss"], }) export class HomePage { 変更・・・ constructor(public platform: Platform, public helloworld: HelloWorldPlugin) { this.platform.ready().then(() => { this.helloworld.echo("ACN").then((message) => { this.successCallback(message); }); }); } ・・・ //成功時の処理 successCallback(message) { alert(message); } //エラー時の処理 errorCallback() { alert("hello error"); } }Git
参考
- 投稿日:2020-09-17T23:26:17+09:00
対象(ImageView)の回転について
はじめに
iPhoneアプリ開発における目標物の回転についての記事を書こうと思います。
先日、私事ではありますが自身初のiPhoneアプリであるルーレットアプリをAppStoreの方に公開させていただきました。
その際にImageViewの回転について実装したので、自分で思い出す意味でも記事にしておこうと思います。実装
回転を実装するにはanimateプロパティにおいて、"CGAffineTransform"を用います。CGAffineTransform(rotationAngle:CGFloat.回転角)とすることで実装できます。
viewController.swiftimport UIKit class ViewController: UIViewController { @IBOutlet weak var rouletteView: UIImageView! @IBOutlet weak var button: UIButton! func rotation() { UIView.animate(withDuration: 1, animations: { self.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.pi) }) } @IBAction func go(_ sender: Any) { rotation() } }以上のように記述すると、回転角が pi = 180°となっているので半回転します。
※ここで注意したいのが、角度の指定にはpiを用いなければならないので、viewController.swiftself.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.45)などとするとエラーが返されます。
なので、細かい角度まで調整したいときは、viewController.swiftself.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.pi/4) self.rouletteView.transform = CGAffineTransform(rotationAngle: 45*CGFloat.pi/180)//などでも正常に動作します。もう一つ問題があります。
例えば、以下のように240°回転させるような記述をしたとします。viewController.swiftself.rouletteView.transform = CGAffineTransform(rotationAngle: 240*CGFloat.pi/180)すると...
このように、120°逆回転しています。
この記述は、確かに240°回転するように書かれています。ただ、機械からすると240°回転したときの"到達点"への回転移動を行っていることになります。したがって、240°右回転するよりも120°左に回ってしまった方が、速く処理できますから左回転してしまうわけです。ということはもちろん以下の記述をしたときは...
viewController.swiftself.rouletteView.transform = CGAffineTransform(rotationAngle: 360*CGFloat.pi/180)解決方法
では、181°~360°での右回転はどのようにしたらいいのかというと...
viewController.swiftself.rouletteView.transform = CGAffineTransform(rotationAngle: 180*CGFloat.pi/180) self.rouletteView.transform = CGAffineTransform(rotationAngle: 240*CGFloat.pi/180)このように、2回に分けて処理を行えば動作します。1行目の
self.rouletteView.transform = CGAffineTransform(rotationAngle: 180*CGFloat.pi/180)で
半回転させてしまえば、そこ(180°)の地点から181°~360°の地点は右回転が最短ルートになるので、そのまま右回転を続けるというわけです。
また、ルーレットのように複数回回転するような場合は、以下のように制御構文を用いてあげれば問題ないです。
viewController.swiftfunc rotation() { UIView.animate(withDuration: 1.5, animations: { let number = Int.random(in: 1..<360) for _ in 0...2{ self.rouletteView.transform = CGAffineTransform(rotationAngle: 180*CGFloat.pi/180) self.rouletteView.transform = CGAffineTransform(rotationAngle: 360*CGFloat.pi/180)//360で1回転 } self.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.pi/180*CGFloat(number)) }) }まとめ
今回、初めてのQiita投稿になったので思っていたよりも時間がかかってしまいましたが、なんとか投稿できてよかったです。文章やコードなど、おかしい点などありましたらコメントいただけると助かります。
また、iOSは14.0にアップデートされXcodeも12.0へバージョンアップしたのでできるだけ速く順応できるようにがんばりたいです!
- 投稿日:2020-09-17T21:14:06+09:00
ArcGIS Runtime SDK:AR (拡張現実) ツールキットと Xamarin によるビルドとデプロイ手順のご紹介
AR アプリについて書きました。
Xamarin による iOS と Android のビルドとデプロイ手順も紹介しています。ArcGIS Runtime SDK:AR (拡張現実) ツールキットと Xamarin によるビルドとデプロイ手順のご紹介
https://community.esri.com/docs/DOC-15422
- 投稿日:2020-09-17T19:25:20+09:00
Flutter で Swift のライブラリがリンクされずにビルド失敗する
問題
Flutter でプラグイン(ネイティブ実装)を含む新しいパッケージを使うようにしたら、突然 Swift 関係のリンクエラーでビルド失敗することがあります。
ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ld: warning: Could not find or use auto-linked library 'swiftCoreLocation' ld: warning: Could not find or use auto-linked library 'swiftCoreFoundation' ld: warning: Could not find or use auto-linked library 'swiftCompatibility50' ld: warning: Could not find or use auto-linked library 'swiftFoundation' ...原因
flutter create -i objc で作成した Flutter アプリから、Swift コードを含むパッケージを参照すると、この問題が発生します。Swift 関係のライブラリの参照設定が全く行われていないからです。
flutter create 時に Swift (デフォルト)が選択されていればこの問題は発生しません。
解決
Flutter の Runner ワークスペース(ios/Runner.xcworkspace) を開いて、何か1つ Swift のコードを追加してやれば治ります。
- Xcode を使って、ios/Runner.xcworkspace を開きます。
- New File... メニューを使って何か1つダミーの Swift ファイルを追加します。
- 「Swift - ObjC 間の Briding-Header.h を作るか」と尋ねられるので、「YES」を選択してヘッダを生成させます。
- 投稿日:2020-09-17T14:24:32+09:00
【iOS 14】SKOverlay を使ってオススメ/関連アプリを紹介する UI をお手軽実装
はじめに
時事雑談
新しい iPhone の発売が遅れるというアナウンスもあって,
iOS 14 のリリースの仕方が気になっていましたが,
9/15 のイベントの中でかなり急な感じでリリース発表がありました。
(えっ明日!? Xcode 12 GM 出てたっけ?)
iOS 14 リリース日に合わせてアプリの配信を。と
考えていたデベロッパも多いはずで間に合うことを祈りたいですね・・・iOS 14 で別のアプリをユーザーに薦め,すぐに App Store でインストール可能にする SKOverlay が使えるようになりました。
実装自体とても簡単で,UIKit,SwiftUI 両方で使えます。
自分の作った別のアプリを紹介するという形で組み込んでみたので
実装していて気づいた点を含め紹介します。
全体の動きはこんな感じです。SKOverlay とは
Developer サイト1 には下記のように説明があります。
By displaying an overlay, you can recommend another app to users and enable them to download it immediately.
オススメしたいアプリやコンテンツに関連するアプリなどを表示させ,
App Store へ遷移させることでユーザがすぐにアプリ情報にアクセス,
アプリインストールが可能になります。今まで App Store へのリンクや UI を用意していたのが,
ほんの少しの実装で代わりになってくれます。
iOS 14 以上対応なので,iOS 13 以下は別途対応が必要です。
(私はあえて iOS 13 以下は何もしないことにしました。)アプリのレビュー促進(
SKStoreReviewController
2)など
簡単な実装で実現できる便利で Good な機能あるので StoreKit いいですよね。SwiftUI
StoreKit
をimport
します。
指定された条件がtrue
の場合に表示されます。
例えばボタンタップで表示させたりができます。import SwiftUI import StoreKit // 追加 struct ContentView: View { // SKOverlayを表示するかの状態 @State private var showSKOverlay = false var body: some View { Button("オススメアプリを表示") { self.showSKOverlay.toggle() // 状態切替 } .appStoreOverlay(isPresented: $showSKOverlay) { SKOverlay.AppConfiguration(appIdentifier: "1234567890", position: .bottom) } } }
appIdentifier
は App Store のアプリページのリンクの
末尾のid
を除いた数字部分を文字列にしたもので,
https://apps.apple.com/jp/app/id1234567890
だったら "1234567890" です。表示位置は 2パターンあり,
.bottom
と.bottomRaised
です。
後者は少し上に上がって表示されます。TabBar とか ToolBar を意識しているのかな?
.bottom
.bottomRaised
Run した場合ビルド自体は通るのですが,プレビューを見ようとしたらできないです。
いつか治るといいのですが・・・・(リリース版でもダメ?)UIKit
私は UIKit の方で対応したので,
このような関数を用意してコールしてみました。
scene に対して present するあたりが特徴でしょうか。import StoreKit // 追加 @available(iOS 14.0, *) private func displayOverlay() { guard let scene = view.window?.windowScene else { return } let config = SKOverlay.AppConfiguration(appIdentifier: self.myAppInfo.appIdentifier, position: .bottom) let overlay = SKOverlay(configuration: config) overlay.present(in: scene) }表示位置は同じで,
.bottom
と.bottomRaised
の2パターンです。ダークモードも対応しているので色の設定等の対応は不要です。
OPEN のところはローカライズされています。(私が英語環境のため)
インストール済みだったら該当のアプリが開きます。インストールされていない場合やボタン以外のビューをタップすると
App Store に遷移します。実装していての気づき
シミュレータでは確認できない
実装してみてシミュレータで動作確認しようとしたところ,
アプリ情報が表示されなくて少し時間を無駄にしました。
iOS 14 の実機で確認すればちゃんと表示されます。スクロール量の調整
表示は画面の下からコンテンツに被さる形となるため,
position を.bottomRaised
にすることで事足りる場合はいいのですが,
コンテンツが隠れてしまうことが多いと思います。
UIScrollView
(もちろんUITableView
やUICollectionView
も)を
使っている場合はスクロール量を少し調整してあげたら良いと思います。
使っていない場合は制約を調整すれば良さそうです。私のアプリは
UIScrollView
を使っていたので
下記のように iOS 14 以上ではコンテンツサイズを調整させました。override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if #available(iOS 14.0, *) { self.baseScrollView.contentSize.height += 100.0 self.displayOverlay() } }一応表示は下にスワイプすると隠れてくれます。
表示/非表示が完了するタイミング,ロードが失敗した際に呼ばれる,
Delegate メソッドが用意されているので,
レイアウトをしっかりしたい場合等はこちらで調整しても良さそうです(SKOverlayDelegate
)。3例えば,表示されたらコンテンツのサイズ変更し,
非表示になったらアニメーションつけてサイズを戻してあげたりできますね。
お手軽感は薄れますがこっちの方が良さそうです。// overlay.delegate = self @available(iOS 14.0, *) extension HogeViewController: SKOverlayDelegate { // SKOverlayの表示が終わったときに呼ばれる func storeOverlayDidFinishPresentation(_ overlay: SKOverlay, transitionContext: SKOverlay.TransitionContext) { self.baseScrollView.contentSize.height += 100.0 } // SKOverlayが非表示になり始めたときに呼ばれる func storeOverlayWillStartDismissal(_ overlay: SKOverlay, transitionContext: SKOverlay.TransitionContext) { UIView.animate(withDuration: 1.0) { self.baseScrollView.contentSize.height -= 100.0 } } }適切なタイミングで非表示に
よく仕様を確認せず表示されたことに満足していたところ,
画面遷移などによって表示させたい画面を離れても
表示されたままになってしまい,UX を損なうことがありました。VC に対しての present ではなく,scene に対しての present のためです。
/// Attempts to present an app overlay in a `UIWindowScene`. @available(iOS 14.0, *) open func present(in scene: UIWindowScene)そのため,非表示にする実装もしっかりしないといけないです。
画面を離れる際に非表示にするように対応しました。override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if #available(iOS 14.0, *) { self.dismissOverlay() } } @available(iOS 14.0, *) private func dismissOverlay() { guard let scene = view.window?.windowScene else { return } SKOverlay.dismiss(in: scene) }おわりに
iOS 14 から使えるようになった SKOverlay について書きました。
お手軽に実装できるので,
もし関連アプリやオススメしたいアプリがあったらぜひ実装したいですね。強調しすぎるのも良くないので適切な画面,タイミングで表示し,
同じく非表示にしてあげるのも大事だと思いました。ご覧いただきありがとうございました?♂️
App Clip でも使えるらしいけどキャッチアップがまだ・・・4
https://developer.apple.com/documentation/storekit/skoverlay ↩
https://developer.apple.com/documentation/storekit/skstorereviewcontroller ↩
https://developer.apple.com/documentation/storekit/skoverlaydelegate ↩
https://developer.apple.com/documentation/app_clips/recommending_an_app_clip_s_corresponding_app ↩
- 投稿日:2020-09-17T08:39:11+09:00
iOS 14 / iPadOS 14 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE, Twitter など)
概要
- iOS 14 / iPadOS 14 上で動作する Web ブラウザやアプリ内ブラウザのユーザーエージェント (User-Agent, UA) 文字列を調べる。
iOS 14.0 + iPhone 11 Pro で確認したユーザーエージェント文字列
Safari
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
Safari (デスクトップ用Webサイトを表示)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15
Google Chrome - ウェブブラウザ (バージョン 85.0.4183.109)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/85.0.4183.109 Mobile/15E148 Safari/604.1
Google Chrome - ウェブブラウザ (PC 版サイトを見る) (バージョン 85.0.4183.109)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/85 Version/11.1.1 Safari/605.1.15
Mozilla Firefox ウェブブラウザー (バージョン 28.1)
Mozilla/5.0 (iPhone; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/28.1 Mobile/15E148 Safari/605.1.15
Microsoft Edge (バージョン 45.8.9)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 EdgiOS/45.8.9 Mobile/15E148 Safari/605.1.15
Opera Touch ウェブブラウザ (バージョン 2.4.5)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) OPT/2.4.4 Mobile/15E148
Sleipnir Mobile (バージョン 4.6.5)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148
Smooz (スムーズ) ブラウザ (バージョン 1.105.3)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/605.1.15/Smooz/1.105.3.3092
Twitter ツイッター (バージョン 8.36)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
Echofon Pro for Twitter (バージョン 13.2.10)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
LINE (バージョン 10.14.0)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari Line/10.14.0
Facebook (バージョン 287.0)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone12,3;FBMD/iPhone;FBSN/iOS;FBSV/14.0;FBSS/3;FBID/phone;FBLC/ja_JP;FBOP/5]
Google アプリ (バージョン 125.0)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/125.0.331040314 Mobile/15E148 Safari/604.1
Yahoo! JAPAN (バージョン 4.22.5)
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 YJApp-IOS jp.co.yahoo.ipn.appli/4.22.5
iPadOS 14.0 + iPad Pro (2018, 11-inch) で確認したユーザーエージェント文字列
Safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15
Safari (モバイル用Webサイトを表示)
Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
Google Chrome - ウェブブラウザ (バージョン 85.0.4183.109)
Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/85.0.4183.109 Mobile/15E148 Safari/604.1
Google Chrome - ウェブブラウザ (PC 版サイトを見る) (バージョン 85.0.4183.109)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/85 Version/11.1.1 Safari/605.1.15
Twitter ツイッター (バージョン 8.36)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15
LINE (バージョン 10.14.0)
Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari Line/10.14.0
関連資料
- iOS 13 / iPadOS 13 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE, Twitter など) - Qiita
- iOS 12 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE, Twitter など) - Qiita
- iOS 11 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE など) - Qiita
- iOS 10.3.3 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE など) - Qiita
- 投稿日:2020-09-17T06:07:13+09:00
Device Orientationで迷ったときに見る記事
向きの一覧
デバイスの向き一覧はこちらの記事にあります。
Orientationのパラメータのまとめ(UIDeviceOrientation, UIInterfaceOrientation)
起動してすぐはデバイスの向きが取れない
UIDevice.current.orientationでデバイスの向きは取れるのですが、アプリを起動してすぐは.unKnownを返すようになっています。
起動してすぐの向きはUIInterfaceOrientationで確認できます。
iOS12まで
UIApplication.shared.statusBarOrientationiOS13以降
self.view.window?.windowScene!.interfaceOrientation*ただし、画面内のインターフェイスの向きなので、
viewが現れていない状態でUIInterfaceOrientationを確認するとnilになります。
viewDidAppear ~ viewWillDisAppear の間で確認するようにします。
また、デバイスを寝かせて置いた状態(.faceUp, .faceDown)は認識できません。
Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。contact:
rockyshikoku@gmail.com