swift codableのデバッグ
型や項目の必須、任意が正しくないと1件もヒットしなくなってしまうのでエラー時のデバックプリントはたぶん必須
Swift
let data = """ [{ "id": 1, "name": "USER1", },{ "id": 2, "namexxx": "USER2", }] """.data(using: .utf8)! struct User: Codable { var id: Int var name: String } do { let users = try JSONDecoder().decode([User].self, from: data) dump(users) } catch { print(error) } }
コンソール
keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1", intValue: 1)], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intVal\ ue: nil) (\"name\").", underlyingError: nil))
の結果より、Index = 1がkeyNotFoundとなっているので2番目のデータがおかしいことがわかる。以上です。
node dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.xxx.dylibエラー
node6がEOLになったのでnode8にあげてfastlaneでionicプロジェクトをビルドしようとしたら以下のエラー発生
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib Referenced from: /usr/local/bin/node Reason: image not found (省略) Command PhaseScriptExecution failed with a nonzero exit code
nodeをインストールしなおせばなおる記事をいくつか見たが解決せず...半日。brewでインストールしていたnodeをndenvでインストールしたらビルドできた。ndenvじゃなくてもbrewを使わなければいいのだろうけど...
以上
carthage SWIFT_VERSION '5.0' is unsupported, supported versions are: 3.0, 4.0, 4.2.エラー
タイトルのエラーの原因と解決策のメモ
今回は「Smile-Lock」というパスコードの入力画面を簡単に実装できるライブラリを使おうとして発生。プロジェクトの都合でxcodeのバージョンは10.1でSwift4.2を使用。
Cartfile
github "recruit-lifestyle/Smile-Lock"
carthage update
$ carthage update Smile-Lock --platform iOS *** Checking out Smile-Lock at "3.0.8" *** xcodebuild output can be found in /var/folders/f8/3j706yps6t97pj4d6b49f5200000gn/T/carthage-xcodebuild.4fxFE3.log *** Building scheme "SmileLock" in SmileLock-Example.xcworkspace Build Failed Task failed with exit code 65: (省略) This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/f8/3j706yps6t97pj4d6b49f5200000gn/T/carthage-xcodebuild.4fxFE3.log
エラーメッセージのログを見てみる
$ cat /var/folders/f8/3j706yps6t97pj4d6b49f5200000gn/T/carthage-xcodebuild.4fxFE3.log (省略) note: Using new build system note: Planning build note: Constructing build description Build system information error: SWIFT_VERSION '5.0' is unsupported, supported versions are: 3.0, 4.0, 4.2. (in target 'SmileLock') Build system information error: SWIFT_VERSION '5.0' is unsupported, supported versions are: 3.0, 4.0, 4.2. (in target 'SmileLock') ** ARCHIVE FAILED **
Swift5なんて使ってないのにと思ってたら勘違いだった。
Carthage/Checkouts/Smile-Lock/SmileLock-Example/SmileLock-Example.xcworkspace の 「Swift Language Version」がSwift5.0が指定されてた
Cartfile
github "recruit-lifestyle/Smile-Lock" "3.0.7"
Swift5対応される前のバージョンを指定してcarthage updateしたらうまくいった。
けどXcodeとSwiftのバージョンそろそろあげないとな...以上です
android ListViewでContextMenuを使う
今回やりたかったことは、ListViewの各行を長押ししたらコンテキストメニューを表示して選択されたメニューによって処理を行うということ
http://kimagureneet.hatenablog.com/entry/2019/02/19/031844
ListViewはこちらに書いたものを使用する
registerForContextMenuでListViewを設定するとonCreateContextMenuが呼ばれるのでこれをオーバーライドしてメニューアイテムを表示するだけだと思っていたらonCreateContextMenuが呼ばれずにハマった...解決策はListViewの行アイテムにisLongClickable = trueをセットすることでした
MainActivity.kt
class MainActivity : AppCompatActivity() { ・・・ override fun onCreate(savedInstanceState: Bundle?) { ・・・ // ListViewにContextMenuを登録 registerForContextMenu(listView) } override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { super.onCreateContextMenu(menu, v, menuInfo) val info = menuInfo as AdapterView.AdapterContextMenuInfo menuInflater.inflate(R.menu.comment_context, menu) } override fun onContextItemSelected(item: MenuItem?): Boolean { val menuInfo = item!!.menuInfo as AdapterView.AdapterContextMenuInfo // メニューを表示した行番号を取得 // menuInfo.position when(item.itemId) { R.id.edit -> { // 編集 } R.id.delete -> { // 削除 } } return true } }
res/menu/user_context.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/edit" android:title="編集"/> <item android:id="@+id/delete" android:title="削除"/> </menu>
Adapter/UserAdapter.kt
class UserAdapter(val context: Context, val users: List<User>): BaseAdapter() { ・・・ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val view = layoutInflater.inflate(R.layout.user_item, parent, false) ・・・ // ★長押しを有効化 view.isLongClickable = true return view } }
以上です
android ステータスバーの文字色を変更する
今回やりたかったことはステータスバーの色を白にして、文字色を黒にしたかったが文字色の変え方が見つからない...
https://stackoverflow.com/questions/30464234/android-lollipop-set-status-bar-text-color
こちらによるとAndroid6以降なら「android:windowLightStatusBar」を指定することでステータスバーの色によって文字色をいい感じに変更してくれるみたい
Android5以下でのやり方がわからなかったので、Androidのバージョンを確認して5以下だったらステータスバーの色を黒っぽくすることにした...
res/values/styles.xml
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="es"> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ・・・ <item name="android:statusBarColor">@color/colorPrimaryDark</item> <item name="android:windowLightStatusBar" tools:targetApi="M">true</item> </style> ・・・ </resources>
MainActivity.kt
class MainActivity : AppCompatActivity() { ・・・ // ステータスバーの色を黒っぽく if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { this.window.statusBarColor = ContextCompat.getColor(this, R.color.abc_primary_text_material_light) } }
以上です
ionic cordova-plugin-ionic-webviewプラグインでアプリインストール直後だけFileプラグインでのファイル処理が動作しなかった原因
誰にも必要とされないと思われる情報
cordova-plugin-ionic-webviewプラグインのバージョンを2.4から4.01にバージョンアップした際になぜかアプリインストール直後だけファイルプラグインによるファイルの読み込みがうまくいかなかった。2回目の起動以降はうまくいくのに、1からプロジェクトから作り直したらうまくいくのに。。各プラグインのバージョンとnpmでインストールされるパッケージのバージョンもすべてそろえたのになぜか...ちなみに試したコードは以下だが、readAsTextのSuccessもFailedもログ出力されない...
export class MyApp { constructor( platform: Platform, statusBar: StatusBar, public file: File ) { platform.ready().then(() => { let dir = cordova.file.dataDirectory; let fileName = 'test'; let json = JSON.stringify({ session:'xxxxxxxxx1' }); this.file.writeFile(dir, fileName, json, { replace: true }).then((result) => { console.log('Success writeFile'); this.file.checkFile(dir, fileName).then((result) => { console.log('Success checkFile'); this.file.readAsText(dir, fileName).then((result) => { console.log('Success readAsText'); }).catch((err) => { console.log('Failed readAsText'); }); }).catch((err) => { console.log('Failed checkFile'); }); }).catch((err) => { console.log('Failed checkFile'); }); }); } }
結論
src/index.htmlでサードパーティのライブラリを読み込んでいてそれが、ionic関連のjsより先に読み込んでいたのが原因でした。これを1番最後に読み込むように修正した動いた。インストール直後だけうまくいかないのは不明だが...こんなので1日つぶした
ionicでのハイブリッドアプリ開発のメリット・デメリットについてそろそろまとめとく
3年くらい前からionicを使い始めて良いところと悪いところが少しつつわかってきたのでメモしておく
メリッド
学習コストが低い & 開発リソースが確保しやすい
swiftやjavaなどでの実装となるとそれぞれのプログラム言語の学習する必要がある。言語自体の学習コストよりもios、androidそれぞれのUIKitというか概念を勉強する必要がありやはり慣れるのにそれなりに時間がかかると思う。その点、ionicだとWebの技術(HTML+CSS+Javascript) がある程度わかっていればなんとなく作れてしまう。またアプリ作り始めてもすごい時間がかかったりすると挫折しがちだがなんとなくでも動くものが作れればあとは慣れなのでこれはメリットかと思う。また、ネイティブだとちょっとしたレイアウト調整や文言変更でもそこそこ経験が必要になるがHTML+CSSだと直感的にもわかりやすく作業できる人が多いのでそういう意味でリソースが確保しやすいと思う。
デメリット
開発環境のバージョンアップが速い
これはメリットというか良いことだとは思うがあえて辛いところもあるということでデメリットの方に書いた。ionic1から2に上がったとき、angular1も2への変更がありangular1と2は全く別物となっていてバージョンアップ=アプリの作り直し ということとなってしまいやはり辛かった。ionicに加えてcordova自体のバージョンが上がるとプロジェクトのファイル構成も変わってしまい、これらを新しい環境にあわせて継続的に対応させ続けていくとなるのでやはり大変。長く続くアプリでは開発環境のバージョンアップも視野にいれないとならない。Swiftもけっこうバージョンアップしてるがangularやcordovaの変更に伴う修正作業と比べたらだいぶ楽なんじゃないかと、、
WebViewベースのガワアプリの開発が難しい
cordova自体の仕組み上の問題だが、アプリの一部にWebViewを組み込むようなアプリの実装が難しい。例えば画面の下タブはionicのコンポーネントを使い、タブを選択するとWebViewが切り替わるようななんてことなさそうなアプリだがこれが難しい。ionicだけで何ができて何が難しいかというのは判断はある程度慣れだとは思うがこういうのが出てくると大変
結論
何年もメンテし続ける必要があるようなアプリだと最終的にかかる工数もネイティブの方が少なくなるんじゃないかと思う。また、失敗が許されないような案件もネイティブの方が確実だと思う。逆にプロタイプのアプリや、画面数が少ないので開発環境のバージョンアップがあってもサクッと作り直せるアプリだとionicがいいのかなと思う。あと今あげたようなデメリットを許容してくれることもけっこうあると思うのでそういう場合もionicで作るのはありだと思う。ionicもけっこうたつのでだいぶ成熟してきた印象はある。flutterには期待してるけど正直まだ勉強中なのでわからん。
結論、どっちがいいかはケースバイケース。けど趣味でアプリ作るなら自分はionicかも、、以上です