Swift4:MesaClip for iOSの進捗

アプリの実装はほぼ終わりました。3月末リリースで進めています。

コンテンツブロックの実装・汎用化をしようと、ソースコードをバックアップしないで、自分の記憶力を過信して、どんどん先に進めたら戻れなくなってしまいました。

仕方がないので、webページの読み込みをscratch and buildでやり直し、それからコンテンツブロックを汎用化することで辻褄を合わせました。

結果として、全体最適ができました。比較的にシンプルになり、パラメタ渡しにしたのでそれぞれのプログラム行数も小さくなりました。

MKWebViewをふたつ使う必要があり、読み込み・コンテンツブロックを汎用化しておかないと、後々、メンテができなくなると思い、やり遂げました。

まだまだ寒い日が続いていますが、それでも、蝋梅(ろうばい)があちこちで咲いています。あと半月もすれば梅が咲きます。春はすぐそこに来ている感じがします。

Screenshot 2018-02-01 21.43.03

Screenshot 2018-02-01 21.45.01

Swift4:javascriptの広告ブロック

iOSはmacOSとjavascript広告のブロックの仕方(手順)が違うことがわかりました。

違いを理解し、さらにiOS(webView)にブロックをまかせる場合、フィルタの持ち方をどうすればいいか理解し、着地するのにすっかり時間がかかってしまいました。

方式としては、プログラムに定義しておく方法(メモリ方式)とファイルに定義しておく方法があります。

iOS 11 WKWebViewで広告などのコンテンツブロックをするが参考になりました。次の点が参考になりました。

  • このサンプルプログラムはメモリ方式とファイル方式があり、ファイルをプログラムに埋め込む場合、必ずしもファイル方式をサポートしなくてもいいのではないか。
  • webViewはstoryboardでなく、プログラムで定義されているので、storyboard対応するには、インターフェースを変える必要がある。
  • フィルタの設定が再帰呼び出しになっている。
  • いくつかのwebViewをハンドリングしたい場合、パラメタ渡しにする必要があるが、再帰呼び出しで矛盾がないように定義する必要がある。
  • DispatchGroup()が使われていることも注意を要する。
  • fileprivateはclass内に定義して良い。また、UserDefaultsと連動していることに注意。
  • フィルタをwebViewに設定する方法があるように、逆にこれをリセット(削除)する方法がある。
  • 動作的には、cookieや広告をブロックした後にjavascript広告を除去することにした。
  • 課題は、削除した広告の空きを詰める処理を明らかにすること。

Screenshot 2018-01-22 23.27.36

Swift4:開発メモ

あまりにもわからないことが多すぎるので、メモをしなければ、何が問題だったかさえもすぐに忘れてしまいます。

以前はNoteを使っていたのですが、めくるのが大変なので、今、カード方式のTwitterとFBページを使っています。将来的には、どちらか一方にしたいのですが、現時点では、日本語をTwitter、英語をFBページにしています。FBページは使い勝手を調べている段階です。文字数制限がないこと、リンクの一目性がいいこと、後から修正ができる点がTwitterと比べていいです。

今はTwitter利用が多いです。TwitterrainsFromRaizan Swift4で検索できます。

FBページはここです。これは、元々、ボランティア活動をするために作ったものです。

Screenshot 2018-01-16 08.04.46

 

Swift4:モーダルをモーダル中から実行

いつものことです。基本的なことがわかっていないため、モーダルをモーダルの中から呼び出す方法がわかりませんでした。

結論的には、呼び出し元でfunc ExModalFinAlert(modalDelegate: String) { }を書き足せばいいでした。この1行がないと、selfでエラーになり、プロンプト通りに修正しても実行時に異常終了します。

1. MainからMesaModalUpdateDelegateを実行する。

2. MesaTableからMesaModalUpdateDelegateを実行する(スクリーンショット参照)。

Screenshot 2018-01-16 07.31.00

 

Swift4:モーダルの呼び出し元ボタンの変更

モーダル表示をして処理をしたとき、呼び出し元のボタンを変更したいとき、どうすればいいか。

多くの場合、呼び出し元で値を設定し、モーダル・ビューを表示してそこで処理をし、呼び出し元に返したくなります。仮に値を返せないとしても、せめて呼び出し元のボタンアイコンだけは変更したい。

例としては、検索エンジンをモーダル・ビュー側で選択・決定します。このあと、検索欄に文字列を入れて検索します。しかし、どの検索エンジンが選ばれているか、ボタン・アイコンが変更されていないと、わかりようがありません。

やり方として、もっとスマートで適切な方法があると思いますが、とりあえずこうすればいいというやり方がわかりました。プログレスバーを変更する箇所にボタン変更を入れておけば、モーダル・ビュー側でボタン変更をすると同時に呼び出し元画面のボタンも自動的に変更されます。

呼び出し元のプログレス処理

@IBAction func ExecIBActionProgressBar(){
self.xProgress.progress         += 0.1
if(self.xProgress.progress >= 1.0) {
self.xProgress.removeFromSuperview()
xWebView.stopLoading()
} else { }
ExecUpdateIcon()//現在の画面アイコンを最新のものに更新する。
}

func ExecUpdateIcon() {//<*画面アイコンを更新する*>
xEngine.setImage(G.engIcon, for: .normal) //検索エンジンのアイコンを更新。
xAdblockOnOff.setTitle(S.staAdsBlockIcon, for: .normal) //広告ブロックのON/OFF。
}

モーダル・ビュー側の処理

Screenshot 2018-01-11 14.58.20

Screenshot 2018-01-11 15.01.24

Swift4:iOSの広告ブロック

macOS版MesaClipをiOSに移植中。ひとつひとつが鬼門でうまくいかず、広告ブロックで2週間くらい立ち止まっていました。

どうしたものかと迷いながら、コンテンツ・ブロックのサンプルプログラムを見つけたので、storyboard版に移植したあと、解析していました。いつか、完全に理解したいと思っています。小さいプログラムですが、UserDefaultsで立ち止まってしまいました。

それで、昨夜、暑くて目が覚めたので、移植中のiOSアプリを眺めていたら、WKWebViewからurlが正しく抽出できていないことがわかりました。

@IBOutlet weak var xWebView:WKWebView!

⭕️ let wURL:String = String(describing: xWebView.url!)
let wURL:String = (xWebView?.url?.path)!

それで全部をString(describing: xWebView.url!) に変更し、デフォルトのフィルタを登録したら、広告のブロックができるようになりました。統計情報は体裁見直しと項番不具合を修正する必要があります。

とりあえず、メインのロジックが通ったので一安心です(周辺にどんな地雷があるかは別)。

Screenshot 2018-01-11 20.39.54

Swift4:Encodeのモーダル実装

想定内でモーダルの実装が進んでいます。

UIButtonにモーダルを実装してMesaClipの実装が進んでいます。まだ初期設定までですが、想定内です。ひとつだけ注意点があります。モーダルアラートを表示した後、ボタンが選択され、その返り値を戻すという流れはいいのですが、この返り値を使ってどこで機能実装するか、それは問題です。

MesaClip for iOSでは、エラーメッセージを出すとき、OK、ミュート、閉じる(キャンセル)の3種類にし、メッセージはモーダルアラート内で処理しました。どのボタンが押されたか、呼び出し元に戻しても処理タイミングが見つからなかったので、返り値は戻さないことにしました。

他方、Encodeの場合、選択されたコードをsaveし、次回呼び出されたときにこのEncodeにチェックを入れれば生合成(→整合性)が保てます。また、WKWebViewを表示するとき、そのEncodeを使えばいいはずです(ここは未実装)。

Screenshot 2017-12-24 11.44.11

macOSからiOSへの移植なのですぐに終わる予定だったのですが、3月までかかりそうな雰囲気になってきました。webViewの仕様が異なるのでどこまで移植できるか、少し不安です。

Swift4:MesaClip for iOSサンプルコード

動作確認のためのサンプルコードです。

サンプルコードはここのMesaClip_iOS 2フォルダがプロジェクトになります。MesaClip for iOSは現在移植中のアプリです。現時点の出来栄えはサンプルコード相当なので公開します。

機能概要:

  • webサイトをアクセスする。
  • 🏁をクリックすると、アラートのモーダル・ビューを開き、メッセージを出力し、OK、Cancel、Suppressのどれがクリックされたか返り値を返します。インターフェースは次の項目になります。名称(タイトル)変更は言語選択により変更する必要があるための措置。
    – app名
    – メッセージ
    – OK名称
    – Cancel名称
    – Suppress名称
    – メッセージ番号:>=1がsuppress対象、<=0はsuppress対象外
    – Suppress管理テーブル
    – 返り値:OK、Cancel、Suppress
  • アラートの処理は、Singletonでclass間で変数を共有して実現しています。これが私にとっては、一番簡単な方法に思えました。
  • なお、Suppressはメッセージ番号により管理しています。MesaAlertを呼び出す前にすでに同じ番号でメッセージを出力しない(Suppress)ことになっていたら、MesaAlertを呼び出さないようにしています。
  • メッセージ番号が0またはマイナスの場合、Suppress対象とせず、そのままメッセージ出力をするようになっています。これは、メッセージを配列で管理したくないときの仕様になります。
  • OK、Cancel、SuppressなどUIButtonの形式をStoryboardの中で簡単に変更できるようにCustomButtonというclassを定義してあります。

Screenshot 2017-12-20 20.34.52

(注意)

  • Suppressをクリックすると、次からメッセージが表示されません。これは機能確認のためのサンプルプログラムですので、再度起動する必要があります。
  • もしかすると、返り値を返さないで、MesaAlertで各ボタンの処理をする必要があるかもしれません。その場合、どこでその処理を行うか、呼び出し元で教えるようにする必要があります。あるいは、汎用化を諦め、MesaAlertを個別のメッセージ番号で判断してその処理を行わせるようにしてもいいです。