Swift Playgroundsで学ぶiOSプログラミング 第92回
過去に作ったプログラムを最新バージョンに最適化
Swift Playgrounds 2.1での問題点をまとめて解消する
2018年06月20日 17時00分更新
前回の最初にも述べたように、Swift Playgroundsのバージョンを2.1にアップデートすると、この連載で以前に紹介したプログラムが動作しなくなることがあります。その場合は、決まって「プレイグラウンドの実行中に問題が起きました」というダイアログが表示され、理由もわからずプログラムの実行が停止してしまうのです。
これは、いわゆるランタイム(実行時)エラーというものです。プログラムの文法が間違っているというわけではなく、実行前のコンパイル時には見つけられないエラーがあとから発生しているのです。
Swiftの文法が間違っていたり、フレームワークのメソッドの名前や引数のラベルが間違っていたりする場合には、プログラムを入力する都度チェックが入り、実行前に察知することができます。その場合には、そのエラーの場所と内容はもちろん、修正するためのヒントや候補まで提示してくれるので、納得しながらエラーを正すことができます。
しかし、ランタイムエラーの場合には、そうはいきません。まず、メッセージからはエラーの場所も内容も分かりません。「コードに誤りがないか確認してください。」と言われても、どこがどう悪いのかわからなければ手の打ちようがありません。エラーが発生する前、最後に実行していた部分は、プレイグラウンドのデバッガ表示をよく見ればわかることもあります。また、表示が確認しやすいコードを埋め込んで、発生箇所をはっきりさせることが可能な場合もあります。それでも、ランタイムエラーの場合には、エラーが発生した場所が原因でエラーになっているとは限りません。それより前に実行した部分に原因がある場合や、利用しているフレームワーク内のメソッドの実行によってエラーが発生することもあり得ます。
以上は、ランタイムエラーの一般論です。このバージョン2.1以降で発生する実行時の問題に限って言えば、それがバグなのか仕様なのかは別として、Swift Playgroundsのビューコントローラーによるビューの扱い方の変化によって発生するようになったことが強く疑われます。この問題に気づいてから、エラーの発生状況を色々と確認し、その対処方法も開拓してきました。それらの対策はまちまちですが、エラーの根本的な要因は同じところにあるように思えるのです。
かなり昔に遡りますが、Swift Playgroundsのバージョンが1.6になって、アクションとして実行するメソッドの定義の前に「@objc」が必要となって以降のプログラムをひととおり見直し、典型的なエラーの発生状況とその対策を見ていくことにしましょう。具体的には第59回のイメージピッカー経由でiPadの内蔵カメラを使った写真撮影のプログラムから見直します。
イメージビューは、使うときに初めて作成する
実は上の図で示した実行エラーの例は、第59回の2番目の例(AsciiClub-59-2)のプログラムで発生したものです。このプログラムでは、ビューコントローラーのプロパティとしてイメージビューのオブジェクトを作成し、viewDidLoadメソッドの中で、それをビューコントローラーのビューとして設定しています。
実はこれがまずいのですが、実行時エラーはそこではなく、写真を撮影し終わってイメージピッカーコントローラーのdidFinishPickingMediaWithInfoのメソッドの中で、イメージピッカーのビューを閉じる部分で発生します。それによって、元のビューコントローラーのビュー、つまりイメージビューが表示されるからだと思われます。
この対処方法は、いろいろと考えられますが、最も簡単なのはイメージビューをビューコントローラーのプロパティとはせずに、写真を撮影後、didFinishPickingMediaWithInfoのメソッドの中で作成しそこに撮影したばかりの画像をセットして、さらにその場でビューコントローラーのビューに設定する方法です。
これは、プログラム自体が実験的なものなので、あまり汎用性のある解決策とは言えないでしょう。しかし、エラーがらみのビューを、なるべくビューコントローラーのプロパティにしないことが有効な場合がある、ということは憶えておくとよいでしょう。
なお、同じ第59回の1番目の例では、ビューコントローラー自体を使っていないので、エラーは発生しません。
この連載の記事
- 第100回 SceneKitの物理現象シミュレーションとアニメーションをARKitに持ち込む
- 第99回 「物理学体」と「物理学場」を設定して物理現象をシミュレーション
- 第98回 SceneKitのノードに動きを加えるプログラム
- 第97回 いろいろな形のノードをシーンの中に配置する
- 第96回 SceneKitの基礎シーンビュー、シーン、ノードを理解する
- 第95回 現実世界の床にボールや自動車のモデルを配置する
- 第94回 ARKitを使って非現実世界との融合に備える
- 第93回 ARKitが使えるiPadを識別するプログラム
- 第91回 iPadの内蔵カメラで撮影した写真を認識するプログラム
- この連載の一覧へ