0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WKWebView からPythonista3 でJavaScript とお戯れあそばせ

0
Last updated at Posted at 2022-12-23

この記事は、Pythonista3 Advent Calendar 2022 の 24 日目の記事です。

👇 : 23 日目

👇 : 25 日目

一方的な偏った目線で、Pythonista3 を紹介していきます。

ほぼ毎日 iPhone(Pythonista3)で、コーディングをしている者です。よろしくお願いします。

以下、私の 2022 年 12 月時点の環境です。

sysInfo.log
--- SYSTEM INFORMATION ---
* Pythonista 3.3 (330025), Default interpreter 3.6.1
* iOS 16.1.1, model iPhone12,1, resolution (portrait) 828.0 x 1792.0 @ 2.0

他の環境(iPad や端末の種類、iOS のバージョン違い)では、意図としない挙動(エラーになる)なる場合もあります。ご了承ください。

ちなみに、model iPhone12,1 は、iPhone11 です。

この記事でわかること

  • ui モジュールのui.WebView について
  • Pythonista3 で WKWebView を使う方法
  • Pythonista3 での JavaScript 開発の console について

Web ブラウザってすごいね。って話

パソコンにもスマホにも、しれっと標準搭載されている Web ブラウザ。

インストールせずとも使えちゃうって、改めて考えてみたら凄いことですね。

Pythonista3 で、Web ブラウザを呼び出す

ui モジュールには、ui.WebView というブラウザを出せる View があります。

URL でサイトにアクセスするのはもちろん、.html ファイルを読み込み表示もできます。

ui.webview | ui — Native GUI for iOS — Python 3.6.1 documentation

UIWebView と WKWebView (それから SFSafariViewController)

UIWebView を使用する App のアップデート期限の延長 - 最新ニュース - Apple Developer

UIWebView にあまり馴染みがないかもしれませんが、Pythonista3 に関しては大いにあります。

Pythonista3 と UIWebView

import ui

#import pdbg

wv = ui.WebView()
print(wv.objc_instance.webView())
#pdbg.state(wv.objc_instance.webView())

ui.WebView よりobjc_util のインスタンスを確認すると:

<UIWebView: 0x148913380; frame = (0 0; 100 100);
  autoresize = W+H;
  backgroundColor = UIExtendedSRGBColorSpace 0.741176 0.741176 0.760784 1;
  layer = <CALayer: 0x280484b60>
>

別に、Pythonista3 が UIWebView 使っててどうということはないのですが、なるほど!って感じですね。

(あ、アプリのこ、更新を、、、)

WKWebView を Pythonista3 で!?

mikaelho/pythonista-webview: WKWebView implementation for Pythonista

有志の方が、objc_util より WKWebView が呼び出せるモジュールを公開してくれています。

インストールの方法として、README にはpip の方法があります。

しかし、実体は 1 ファイル(wkwebview.py )なので、コピーして貼り付けでも問題ありません。

私の場合は、console 関係でエラーが出てしまうので、フォークして(ほんの)一部の書き換えたものを使っています。

pome-ta/pythonista-webview: WKWebView implementation for Pythonista

SFSafariViewController について(ちょっとだけ)

App におけるウェブビューを実現するには、WKWebView と SFSafariViewController のどちらを使うべきですか - 見つける - Apple Developer

普段使わないので、紹介のみです。

Pythonista/SafariViewController.py at master · tdamdouni/Pythonista

サンプルコードがありますが、起動してみると「ああ、なるほど。これか」という見た目の View でサイトを閲覧できます。

開発ニーズにより、適宜使い分けするのが良さそうですね。

wkwebview.py を使った開発

ui.WebView すら使ったことがない方には、酷な内容かもしれませんが WKWebView をwkwebview.py より呼び出して使う開発をしていきます。

素敵にモジュール化されているので、ui.WebView に近しい使い方になっています。

感覚を掴むために、ui.WebView で一通り操作してから、wkwebview.py モジュールにチャレンジしてもいいかもしれません。

また、JavaScript を知っている前提で話を進めてしまいます。なるべく、参考になりそうなリンクを提示します。

ディレクトリ構成

今後、以下の構成を想定し解説を進めます。

.
├── main.py            <- Pythonista3 でView を呼び出す部分
├── docs               <- html の世界
│   ├── index.html
│   ├── css
│   │   └── style.css
│   └── js
│       └── main.js
└── wkwebview.py       <- リポジトリのを直接貼り付けしている

ただただ、私が使いやすい構成です。使いやすく変更いただいても構いません。

docs 名は、GitHub pages 設定の昔の名残りです。。。

wkwebview.py を読み込む

main.py で、実行をし Pythonista3 より View を表示させます:

main.py
import sys
from pathlib import Path

import ui

sys.path.append(str(Path.cwd()))
from wkwebview import WKWebView


class View(ui.View):
  def __init__(self, url, *args, **kwargs):
    ui.View.__init__(self, *args, **kwargs)
    self.wv = WKWebView()
    self.wv.load_url(str(url))
    self.wv.flex = 'WH'
    self.refresh_webview()
    self.add_subview(self.wv)
    self.set_reload_btn()

  def will_close(self):
    self.refresh_webview()

  def set_reload_btn(self):
    self.refresh_btn = self.create_btn('iob:ios7_refresh_outline_32')
    self.refresh_btn.action = (lambda sender: self.refresh_webview())
    self.right_button_items = [self.refresh_btn]

  def create_btn(self, icon):
    btn_icon = ui.Image.named(icon)
    return ui.ButtonItem(image=btn_icon)

  def refresh_webview(self):
    self.wv.clear_cache()
    self.wv.reload()


if __name__ == '__main__':
  uri_path = Path('./docs/index.html')
  view = View(uri_path)
  view.present(style='fullscreen', orientations=['portrait'])

./docs/index.html で、index.html をロードして実行をさせています。

wkwebview.py に関しては、決してお行儀がいい書き方とは言えませんが、同階層にファイルが存在しているので、無理矢理読み込ませています:

sys.path.append(str(Path.cwd()))
from wkwebview import WKWebView

また、執拗にreload やらrefresh 処理をしています。。。

WebAudio 関係の実装時に、以前実行した音が残っていたりと、謎挙動をしておりまして、それを潰すために執拗に繰り返しています。

.html.js 側のこと

./docs 内のファイルたちは、良きように設定いただければと思います。

例えばですが:

index.html
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <script type="module" src="./js/main.js"></script>
  <title>Pythonista3 でWebView</title>
</head>

<body>
<h1>ほげ😇</h1>
</body>
</html>

./docs/js/ 内に、main.js と、module.js を作成したとします。

main.js
import { fnc1 } from './module.js';

const pTag = document.createElement('p');
pTag.textContent = 'js より☺️';

document.body.appendChild(pTag);

const pImport = fnc1();
document.body.appendChild(pImport);

console.log('main');

main.js からmodule.js をインポートするかたちとして:

module.js
function fnc1() {
  const pModule = document.createElement('p');
  pModule.textContent = 'module.fnc1 より😎️';
  console.log('module');
  return pModule;
}

export { fnc1 };

これでmain.py を実行すると、module.js もインポートされ処理されていることがわかります。

エクスポートとインポート

ECMAScript モジュール · JavaScript Primer #jsprimer

ローカルサーバーをたてなくても、module 機能が使えるのです。

ES Modules 入門 - JavaScript でモジュールを使う時代 - ICS MEDIA

JavaScript の console を確認したい

とはいえ、さっきの js のコードにもあったconsole.log の確認の手立てがないですよね?

ほぼ完成したファイルを Pythonista3 へ持ってきて実行するのであれば、問題はなさそうです。

しかし、Pythonista3(スマートフォン)でも開発したいんじゃ!って声は多数あると思います(私だけ?)。

Console for Mobile Browsers. その名は Eruda

Eruda: Console for Mobile Browsers

liriliri/eruda: Console for mobile browsers

1 行のコードでモバイルブラウザに開発者ツールを搭載できる JavaScript ライブラリ「Eruda」を使ってみた! - paiza 開発日誌

これです(直球)。

Eruda のインポート

気軽に試したい or 数回の確認でいい。のであれば、CDN 経由で実装が可能です。

今回は個人的な理由(ただ好きなだけ)で、Skypack から持ってくることにします。

Skypack: search millions of open source JavaScript packages

Native ESM 時代のフロントエンドビルドツールの動向

.htmlimport eruda from 'https://cdn.skypack.dev/eruda'; を追記しeruda.init(); するだけで使えます。

index.html
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <script type="module">
    import eruda from 'https://cdn.skypack.dev/eruda';
    eruda.init();
  </script>
  <script type="module" src="./js/main.js"></script>

  <title>Pythonista3 でWebView</title>
</head>

<body>
<h1>ほげ😇</h1>
</body>
</html>

npm:eruda | Skypack

ギガが気になるならローカルに入れる方法も

実行時に毎回、CDN へ取りにネットワーク(ギガ)を使うのも、色々と無駄感がありますね。

私の場合は、ローカルに格納し呼び出しをしています。

(バージョンの固定をすれば済む話ですが)うっかりバージョンが上がっており、自分で書いたコードのバグなのか、バージョンが原因なのか調査が煩雑化する可能性があります。

Pythonista3 で尚且つobjc_util で呼び出している WKWebView を使った、特殊な中の特殊な環境での実行なので、疑うべき原因はなるべく排除した方が精神衛生上楽です。

Node とか npm とか webpack とか

もちろんですが、今回実行している JavaScript は、ブラウザ上で実行されている JavaScript です。

つまり Node.js 環境想定のコードは動きません(もちろん TypeScript も)。

JavaScript とは · JavaScript Primer #jsprimer

JavaScript 入門

世の中の js のコードには、node を経由した build 処理を前提としたコードがたくさんあります。

Pythonista3 で動かしたい場合、何がどのように処理をされているのか、実際にコードを見に行って確認し「これできないかも。。。」な場面もあるかもしれません。

node module で書かれたコードを ES Modules へ、丹精込めて手作業で書き換えるのもなかなかオツなものですが。。。

次回は

まさか、Python 実行環境の Pythonista3 で JavaScript 書くことになるとは思いも寄らぬですよね。

Web ブラウザという、すごいマルチプラットフォームでは JavaScript 一択なので JavaScript を楽しみましょう。

eruda があるので、モバイルブラウザでもやみくもに開発せずに済むのが最高な点ですね。

次回は、Pythonista3(WKWebView) と JavaScript の連携の例を、私の大好きな WebGL を実装しつつ紹介していきたいと思います。

ここまで、読んでいただきありがとうございました。

👇 : 25 日目

せんでん

Discord

Pythonista3 の日本語コミュニティーがあります。みなさん優しくて、わからないところも親身に教えてくれるのでこの機会に覗いてみてください。

書籍

iPhone/iPad でプログラミングする最強の本。

その他

  • サンプルコード

Pythonista3 Advent Calendar 2022 でのコードをまとめているリポジトリがあります。

コードのエラーや変なところや改善点など。ご指摘や PR お待ちしておりますー

  • Twitter

なんしかガチャガチャしていますが、お気兼ねなくお声がけくださいませー

  • GitHub

基本的に GitHub にコードをあげているので、何にハマって何を実装しているのか観測できると思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?