Watch版それぞれのアプリをシミュレーター上で実行することができますが、困るのは両機でデータをやり取りしたい時にブレイクポイントが片方でしか効かず、手探りでしかデバッグできないことです。WatchとiPhoneの両方でアプリを実行でき、デバッガも両方で機能します。Watch版にします。ビルドして実行(⌘R)します。Xcode上からではなくSimulator上のiPhoneアプリをタップして実行します。Watch版のままにしておく」ことです。WatchとiPhoneでデータをやり取りする方法については次回以降ご紹介します(お急ぎの方は直接ご連絡またはコメントください)。(3)Swiftに書き換える際に最初分からなくて困ったのは、SwiftにNSArrayとArrayの両方のクラスが存在することでした。自動変換ツールSWIFTIFYを使ったのですが、自動変換では変換後のコードにエラーが出て使えなかった上、配列を必要としたのがTableViewControllerだったため、随所にエラーが現れ、その数の多さにしばらく頭を抱えてしまいました。https://objectivec2swift.com/#/home結果的にArrayとNSArray、2つのクラスの違いはこうでした。Arrayクラスは値型、NSArrayは参照型NSArrayだったものをArrayにしたければ「let」で宣言。NSMutableArrayだったものをArrayにしたければ「var」で宣言。Array、NSArrayそれぞれ使えるメソッドが違うので、片方にしかないメソッドがどうしても必要な場合はそちらを使うしかない。Array()のように書くのだとてっきり思っていたので、自動変換後の式はあまりにシンプルで最初意味がわかりませんでした。[Any]は「中身はなんでもありの配列」ということですね。Cではそれすらもわざわざ宣言したりしないので「違うな」と思いました。NSArrayでは、配列の中身のクラスがなんであるかは、そのクラスのメソッドが必要になるまで何も言う必要がないですよね。メソッド名]のようにキャストすればいい。NSManagedObjectのようにしても良かったのですが、試行錯誤していくうちに、なんのことははない、中身は常にNSManagedObjectなんだから[NSManagedObject]で良いということで手直ししました。asでキャスティングが必要なのは配列に複数のクラスのオブジェクトが混在する場合ですね。そんな怖いことはしませんが。あと、NSMutableArrayをそのままSwiftで使うことも考えたのですが、実際にはmutablecopyで複製して使っていたので、参照型のNSMutableArrayではなく、値型のArrayが良いということになりました。Dataに保存されたデータをTableViewに表示するときの処理です。notesにはNSManagedObjectが入ってます。「textString」という名前は私が決めたものでattribute名です。Dataはデータベースではないとあちこちに書かれていますが厳密な定義は入門者を混乱させるだけだと個人的には思っていて、最初はとにかく動けばいいと思います)。CでvalueForKeyで呼び出していた値はSwiftではvalue(forKeyPath:)と微妙に異なる呼び出し方が必要だったので手直ししました。to.row)TableViewの行を並べ替えたときの処理です。objectToMoveは一時的に用意した移動するNSManagedObjectオブジェクト。CでtoIndexPathだったものはSwiftではtoに変わっています。英語圏の人にはswiftの方がより読みやすくなっているのでしょうが、英語の構文で考えていない日本人にはtoだけだと言葉が短すぎて分かりにくい。TableViewDelegate標準のプロパティ名なので慣れるしかないですね。indexPath.row)TableViewの列を削除したときに使います。これは見たまんまですね。removeObjectAtIndexがremove(at:)と簡略化されています。同じSwift同士でもバージョンアップごとに言い回しがよく変わるので、私はあえて暗記しないことにしています。{直接Arrayの話ではありませんが、配列といえば必ずforループが必要になるので追記します。何番目の要素を処理しているかが大事な場合は自動変換のように整数iを使い、大事でない場合はnotesの各要素をnoteに代入する別候補の式が使えます。{のように記述します。上の式だとiは0,2,4,6,8,10の順に変化していきます。Up」では正規表現を使ってテキストフィールド内の文字列から数字だけを検知して、その合計を表示するということをやっています。計算機とメモ帳を行ったり来たりする必要がこのアプリを使うとなくなります。CからSwiftに完全移行したのですが、エラーは消えたものの問題が一つ発生してしまいました。アラビア語キーボードで数字が入力されると落ちてしまうのです。Cのコード大まかな流れとしてはまずpatternというNSStringオブジェクトに正規表現式を入れて、文字列全体から数字を検索します。error:NULL];_thousandSeparatorForRegExの中身は@”,”か@”.”。これは地域によっては数字の千を1,000ではなく1.000と書くためです。_decimalCharacterForRegExも同様の趣旨です。小数点をコンマ(,)で書く地域に対応させます。alloc]init];forループでパラグラフ、つまり一行ごとに切り分けた文字列をthisLineに格納し、さらに空白で分割してwordsという配列に入れました。thisLineWithAttributionは後で文字に色を付けるためのものですが今回のテーマとは関係ないので省略します。withString:@”.”]doubleValue];さらにwordごとに巡回するforループを中に作ります。正規表現に当てはまるもの全てをmatchesに格納します。matchesの各要素を再度forループでmatchに格納して、ようやく数字部分の【文字列の】抽出が完了です。matchからmatchStringというNSStringに変換して、さらに$3、つまりテンプレートの三番目の要素のみを取り出します。(数字部分)というように切り分けるようになっています。thisNumberには最後の数字部分からさらにコンマを取り除き、小数点をピリオド(.)に統一したものを文字列として代入します。٦も正しく「1234.56」に変換されていました。Swift変換直後のコード問題になったのは上のコードの最後の一行、thisNumberの部分です。Swiftでは当初次のように記述しました。“0”)!やろうとしていることは上と同じでnumberPartというStringからthousandSeparatorを取り去って、小数点をピリオドで置き換えようというものです。“0”はXcodeの警告メッセージに従って加えた変更です。最後の)!も同様です。最初はエラーが消えたからまあいいかぐらいに考えていました。Cからやってきた私にはこの?と!が曲者でした。Cのようにnilをすんなり渡せないことは知っていました。someString!someStringは絶対にnilではないから強制的にアンラップ(unwrap)してオプショナル型を解除せよというように処理したのでした。実際、上のSwiftコードで1234567890は認識できていたのです。※ちなみにただunwrapするだけならsomeString?で大丈夫です。本記事冒頭のスクリーンショットのキーボード一番上の段を見てもらうと分かりますが、アラビア語キーボードにおける数字は我々が使っている数字とは異なります。1、2、3と9と0は似てますね。アラビア語が由来だからアラビア数字というのかと思いましたが、どちらも呼び名がアラビア数字なのが困りものです。上述のthisNumberの式の最後で!で強制アンラップすると、アラビア語キーボードの数字のときだけクラッシュしてしまうということが、ユーザーさんからの報告で分かりました。!をやめて、thisNumberをオプショナル型にすればいいのでは、と思ったのですが、それも問題がありました。thisNumber)この式がthisNumberがオプショナル型だと処理を受け付けてくれないのです。結局次のように書き換えることで解決しました。final!)}}つまりアラビア語キーボードの数字をUSロケールの1234567890に置き換えてから強制案ラップするというやりかたです。実は全角数字でも同じ処理が必要だったあとから分かったことですが、日本語キーボードで全角数字を入れた場合でも、この修正を加えないとやはり落ちてしまうのでした。正規表現上は数字として拾い上げられるが、数字には変換できない文字種が複数あるということですね。最初は解決策がなかなかみつからず、いっそ0〜9までの文字を一個ずつ置き換えて取り急ぎのクレーム対策としようかとも思ったのですが、世界中で使われている自分のアプリが一体何語で使われているか見当もつきませんから、クレームのたびにアップデートするのはやはり得策ではない。頑張って正しい処理方法が見つけることができてよかったです。それにしても、日本のユーザーさんからクレームが来る前に、アラビア語圏の方が先に教えてくれて本当にラッキーでした(その方の優しい口調にも救われました)。いずれにせよ、自分のアプリが世界中で使われていると思うと嬉しいですね。CからSwiftに書き換えた時の体験談です。・.hファイル、.mファイルに相当する.swiftファイルを追加する。・変換ツールを使って.h、.mファイル内のコードをSwiftに書き換え、.swiftファイルに貼り付ける・エラーが出た場合は手直しする・必要があればStoryboardと.swiftファイル内のIBOutlet、IBActionを繋ぎ直す・AppDelegateを新規のswiftプロジェクトからコピーする・.h、.mファイルの中身を全てコメントアウトして無効にし、.mainと移行中に発生したbridging-header.hファイルを削除する。header?」と訊かれるので、Yesを選びます。CのプロジェクトにSwiftファイルを追加して、両言語を混在させたいときに両者の間の橋渡しをするヘッダーファイルです。CベースのViewControllerが他に残っていても、アプリを走らせてテストしたかったので追加しました。CからSwiftに書き換えるのには以下のサイトを使いました。https://objectivec2swift.com/#/converter/無料で変換できるのは1000文字までで、.hファイルは収まっても、mファイル丸ごとは無理でした。有料プランも考えたのですが、まず第一に私がケチなのと(笑)、後から分かったことですが、どの道手直しが必要になるので、コードを少しずつ(メソッドごとかもっと狭い範囲で)コピペして、このサイトとXcodeを行き来しました。他のツールも試しましたが、やり方が悪かったのか上手く行かず、途中で嫌になってやめました。・全てのViewControllerをSwift化してからテストしようとすると、大量のコンパイルエラーを先に解決しなければならないのでお勧めしません。私の場合は合計で約200個のエラーを手作業で取り除かなければなりませんでした。Cの方(.hと.m)をコメントアウトして(ショートカットは⌘/です)、プロジェクトを実行して動作を確認してから次のViewControllerに取り掛かるようにしました。“<#YourProjectName#>-Swift.h”を追加します。Cを呼ぶときは、YourProject-Bridging-Header.hに以下を加えます。Overflow・AppDelegateをSwift化します。SwiftNextを押すこれでAppDelegate.h、.mファイルをコメントアウトして上手く走ればOKですが、ダメな場合はSwiftで新規プロジェクトを作成して、そのAppDelegate.swiftからコピペするのが良いでしょう。・元のAppDelegate.mに書き加えたメソッドなどもSwiftに書き換えてAppDelegate.swiftに書き加えます。・AppDelegateがSwiftになったのでmain.mを削除します。・全てのクラス、ViewControllerがSwiftに書き換えられたら、不要になったYourApp-Bridging-Header.hも削除します。Cの時とは挙動が変わってしまっていることがあります。次回はそのことについて書きます。新規投稿をメールで受け取るにはメールアドレスを記入してください。