20200917のiOSに関する記事は7件です。

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.js
var 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.swift

import 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.ts
import { 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.git

ionic-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 HelloWorldPlugin

gulpが未インストールの場合はインストール

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.ts
import { 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.ts
import { 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

ここにコード置いてます

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

対象(ImageView)の回転について

はじめに

iPhoneアプリ開発における目標物の回転についての記事を書こうと思います。
先日、私事ではありますが自身初のiPhoneアプリであるルーレットアプリをAppStoreの方に公開させていただきました。
その際にImageViewの回転について実装したので、自分で思い出す意味でも記事にしておこうと思います。

実装

回転を実装するにはanimateプロパティにおいて、"CGAffineTransform"を用います。CGAffineTransform(rotationAngle:CGFloat.回転角)とすることで実装できます。

viewController.swift
import 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°となっているので半回転します。
ezgif.com-gif-maker.gif
※ここで注意したいのが、角度の指定にはpiを用いなければならないので、

viewController.swift
    self.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.45)

などとするとエラーが返されます。
なので、細かい角度まで調整したいときは、

viewController.swift
    self.rouletteView.transform = CGAffineTransform(rotationAngle: CGFloat.pi/4)
    self.rouletteView.transform = CGAffineTransform(rotationAngle: 45*CGFloat.pi/180)//などでも正常に動作します。

と記述すれば動作します。
ezgif.com-gif-maker (1).gif

もう一つ問題があります。
例えば、以下のように240°回転させるような記述をしたとします。

viewController.swift
    self.rouletteView.transform = CGAffineTransform(rotationAngle: 240*CGFloat.pi/180)

すると...
ezgif.com-gif-maker (2).gif
このように、120°逆回転しています。
この記述は、確かに240°回転するように書かれています。ただ、機械からすると240°回転したときの"到達点"への回転移動を行っていることになります。したがって、240°右回転するよりも120°左に回ってしまった方が、速く処理できますから左回転してしまうわけです。

ということはもちろん以下の記述をしたときは...

viewController.swift
    self.rouletteView.transform = CGAffineTransform(rotationAngle: 360*CGFloat.pi/180)

sample.png
見事ですね!微動だにしません笑

解決方法

では、181°~360°での右回転はどのようにしたらいいのかというと...

viewController.swift
    self.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°の地点は右回転が最短ルートになるので、そのまま右回転を続けるというわけです。
ezgif.com-gif-maker (3).gif

また、ルーレットのように複数回回転するような場合は、以下のように制御構文を用いてあげれば問題ないです。

viewController.swift
    func 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))

        })

    }

ezgif.com-gif-maker (4).gif

まとめ

今回、初めてのQiita投稿になったので思っていたよりも時間がかかってしまいましたが、なんとか投稿できてよかったです。文章やコードなど、おかしい点などありましたらコメントいただけると助かります。
また、iOSは14.0にアップデートされXcodeも12.0へバージョンアップしたのでできるだけ速く順応できるようにがんばりたいです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ArcGIS Runtime SDK:AR (拡張現実) ツールキットと Xamarin によるビルドとデプロイ手順のご紹介

AR アプリについて書きました。
Xamarin による iOS と Android のビルドとデプロイ手順も紹介しています。

ArcGIS Runtime SDK:AR (拡張現実) ツールキットと Xamarin によるビルドとデプロイ手順のご紹介
https://community.esri.com/docs/DOC-15422

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 のコードを追加してやれば治ります。

  1. Xcode を使って、ios/Runner.xcworkspace を開きます。
  2. New File... メニューを使って何か1つダミーの Swift ファイルを追加します。
  3. 「Swift - ObjC 間の Briding-Header.h を作るか」と尋ねられるので、「YES」を選択してヘッダを生成させます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS 14】SKOverlay を使ってオススメ/関連アプリを紹介する UI をお手軽実装

はじめに

時事雑談新しい iPhone の発売が遅れるというアナウンスもあって,
iOS 14 のリリースの仕方が気になっていましたが,
9/15 のイベントの中でかなり急な感じでリリース発表がありました。
(えっ明日!? Xcode 12 GM 出てたっけ?)
iOS 14 リリース日に合わせてアプリの配信を。と
考えていたデベロッパも多いはずで間に合うことを祈りたいですね・・・

iOS 14 で別のアプリをユーザーに薦め,すぐに App Store でインストール可能にする SKOverlay が使えるようになりました。

実装自体とても簡単で,UIKit,SwiftUI 両方で使えます。
自分の作った別のアプリを紹介するという形で組み込んでみたので
実装していて気づいた点を含め紹介します。
全体の動きはこんな感じです。

SKOverlay_00

SKOverlay とは

<iOS>-<iOS 14.0 and later> <Xcode>-<Xcode 12.0 and later>

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 以下は何もしないことにしました。)

アプリのレビュー促進(SKStoreReviewController2)など
簡単な実装で実現できる便利で Good な機能あるので StoreKit いいですよね。

SwiftUI

StoreKitimport します。
指定された条件が 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
スクリーンショット 2020-09-16 5 53 38 スクリーンショット 2020-09-16 5 54 04

Run した場合ビルド自体は通るのですが,プレビューを見ようとしたらできないです。
いつか治るといいのですが・・・・(リリース版でもダメ?)

スクリーンショット 2020-09-16 14 13 07

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パターンです。

SKOverlay_01

ダークモードも対応しているので色の設定等の対応は不要です。

SKOverlay_02

OPEN のところはローカライズされています。(私が英語環境のため)
インストール済みだったら該当のアプリが開きます。

インストールされていない場合やボタン以外のビューをタップすると
App Store に遷移します。

実装していての気づき

シミュレータでは確認できない

実装してみてシミュレータで動作確認しようとしたところ,
アプリ情報が表示されなくて少し時間を無駄にしました。
iOS 14 の実機で確認すればちゃんと表示されます。

SKOverlay_simularor_bottom

スクロール量の調整

表示は画面の下からコンテンツに被さる形となるため,
position を.bottomRaised にすることで事足りる場合はいいのですが,
コンテンツが隠れてしまうことが多いと思います。

UIScrollView(もちろん UITableViewUICollectionViewも)を
使っている場合はスクロール量を少し調整してあげたら良いと思います。
使っていない場合は制約を調整すれば良さそうです。

私のアプリは UIScrollView を使っていたので
下記のように iOS 14 以上ではコンテンツサイズを調整させました。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if #available(iOS 14.0, *) {
        self.baseScrollView.contentSize.height += 100.0
        self.displayOverlay()
    }
}

SKOverlay_03

一応表示は下にスワイプすると隠れてくれます。

SKOverlay_04

表示/非表示が完了するタイミング,ロードが失敗した際に呼ばれる,
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
        }
    }
}

SKOverlay_06

適切なタイミングで非表示に

よく仕様を確認せず表示されたことに満足していたところ,
画面遷移などによって表示させたい画面を離れても
表示されたままになってしまい,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)
}

SKOverlay_05

おわりに

iOS 14 から使えるようになった SKOverlay について書きました。

お手軽に実装できるので,
もし関連アプリやオススメしたいアプリがあったらぜひ実装したいですね。

強調しすぎるのも良くないので適切な画面,タイミングで表示し,
同じく非表示にしてあげるのも大事だと思いました。

ご覧いただきありがとうございました?‍♂️

App Clip でも使えるらしいけどキャッチアップがまだ・・・4

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

関連資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Device Orientationで迷ったときに見る記事

向きの一覧

デバイスの向き一覧はこちらの記事にあります。
Orientationのパラメータのまとめ(UIDeviceOrientation, UIInterfaceOrientation)
スクリーンショット 2020-09-17 6.01.56.png

起動してすぐはデバイスの向きが取れない

UIDevice.current.orientationでデバイスの向きは取れるのですが、アプリを起動してすぐは.unKnownを返すようになっています。

起動してすぐの向きはUIInterfaceOrientationで確認できます。

iOS12まで

UIApplication.shared.statusBarOrientation

iOS13以降

self.view.window?.windowScene!.interfaceOrientation

*ただし、画面内のインターフェイスの向きなので、
viewが現れていない状態でUIInterfaceOrientationを確認するとnilになります。
viewDidAppear ~ viewWillDisAppear の間で確認するようにします。
また、デバイスを寝かせて置いた状態(.faceUp, .faceDown)は認識できません。


Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

Twitter
MLBoysチャンネル
Medium

相棒
note

contact:
rockyshikoku@gmail.com

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む