Androidはワンツーパンチ 三歩進んで二歩下がる

Android卵プログラマーの記録ブログ

iOSでRealmのデータファイルの場所の見つけ方

初期データのあらかじめ入ったRealmのファイルを用意しておき、
アプリに組み込んで使いたいと思っています。
それにはデータが入ったDBのファイルが必要です。
Realmの保存場所を特定する方法をメモしておきます。

前提

環境はXcode9.2、Swift4.0を使用しています。
初期データ作成用のXcodeプロジェクトを作っておきます。
実機かシミュレーターにRunしておきます。

シミュレーターにインストールした場合の場所

    // DBのファイルの場所
    print(Realm.Configuration.defaultConfiguration.fileURL!)

このコードでファイルパスを表示してくれます。
f:id:sakura_bird1:20180124152523p:plain

これをコピーします。

finderを開いてCommandキー+Shiftキー+Gを押します。

先ほどのパスを貼り付けます。
f:id:sakura_bird1:20180124153944p:plain:w200

先頭の「file://」は削除して移動します。

実機にインストールした場合

Xcodeのメニューから Window > Devices and Simulators を選択します。

実機にインストールされているアプリが一覧で表示されます。

アプリを選択します。

左下の設定アイコンをクリック > “Download Container…“を選択します。
f:id:sakura_bird1:20180124153205p:plain:w300


保存ダイアログが開きます。プロジェクトルートがデフォルトの保存場所になっています。
◯◯.xcappdataという名前がセットされているのでそのまま保存します。

Finderで保存した場所を開きます。
◯◯.xcappdataを右クリックして「パッケージの内容を表示」(英語表示の場合「“Show Package Contents”」)をクリックします。
f:id:sakura_bird1:20180124153450p:plain:w300

ここにあります。
AppData / Documents / default.realm
f:id:sakura_bird1:20180124153600p:plain:w300

以上です。

iOSのNsPredicateを使ってスペース区切りの文字列の検索条件を指定する&RealmでDBから読み込むメモ

こんにちは。自分の勉強メモです。
間違っていたらお声がけ下さると嬉しいです(●´ω`●)

前提

環境はXcode9.2、Swift4.0を使用しています。
Realmを使ったDBの処理を書いている最中です。

やりたいこと

よくあるキーワード検索がやりたいです。
・スペース区切りの文字列を入力された時に、スペースで文字列を分割する。
・対象のフィールドに分割した文字列がそれぞれ含まれているものを抽出する。

このように検索条件を入力したとすると
f:id:sakura_bird1:20180123224904p:plain


SQL文は次のようになります。

SELECT  "foods".* FROM "foods" WHERE (("foods"."name" LIKE '%たま%' OR "foods"."search_word" LIKE '%たま%') AND ("foods"."name" LIKE '%豆%' OR "foods"."search_word" LIKE '%豆%'))

この例では"foods"というテーブルから"name"または"search_word"というフィールドに
入力した文字列があった時にデータが抽出されます。

検索条件を指定するには

NsPredicateクラスを使っての検索条件を指定するのが定石のようです。
RealmでもNsPredicateがサポートされておりNSPredicate Cheatsheetという資料が用意されています。
NSPredicate Cheatsheet

前処理

検索する文字列をスペースで分割して配列に入れておきます。
有効な文字列が入っている前提です。

    let words = " たま 豆"
    // 全角スペースを半角スペースに置き換え余計なスペースはトリムする
    let newWords = words.replacingOccurrences(of: " ", with: " ").trimmingCharacters(in: .whitespacesAndNewlines)
    // componentsメソッドで指定の区切り文字で配列に分割する
    let wordsArray = newWords.components(separatedBy: " ")
    print(wordsArray) // ["たま", "豆"]

NsPredicateに条件を指定する

Swiftでは「let predicate = NSPredicate(format: "search_word CONTAINS %@", "たま")」
のようにformatに条件文を入れていきます。
NSPredicate - Foundation | Apple Developer Documentation

私の例ですと、SQLのLIKE、つまり文字列の部分一致に対応するオペレーターは
「CONTAINS」を使います。

また、比較したい文字列が複数あるかもしれない前提なので
NSPredicateオブジェクトを配列に格納してから「NSCompoundPredicate」クラスを利用してそれぞれの条件を結合します。
AND条件なので「andPredicateWithSubpredicates」を指定します。
比較したい文字列が1つしかなくてもこのコードで問題ありません。

    var predicates: [NSPredicate] = []

    for word in wordsArray {
      predicates.append(NSPredicate(format: "search_word CONTAINS %@ OR name CONTAINS %@", word, word))
    }

    print(predicates)// [search_word CONTAINS "たま" OR name CONTAINS "たま", search_word CONTAINS "豆" OR name CONTAINS "豆"]

    let compoundedPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)

    print(compoundedPredicate)//(search_word CONTAINS "たま" OR name CONTAINS "たま") AND (search_word CONTAINS "豆" OR name CONTAINS "豆")

Realmで検索する

filterメソッドに先程のNSCompoundPredicateオブジェクトをセットすればOKです。
公式ドキュメントはこちらです。
https://realm.io/docs/swift/latest/#queries

let result = realm.objects(Foods.self).filter(compoundedPredicate)

以上です。

オンラインブートキャンプ iPhoneアプリコース



Swift4のCodableプロトコルをRealmのモデルクラスに適用してJsonをパースした後にDBに投入するサンプル

RealmのモデルクラスにSwift4のCodableプロトコルを実装したいと思いましたのでサンプルを作りました。
環境はXcode9.2、Swift4.0を使用しています。
作成にあたってこちらのスライドを参考にさせていただきました。
ありがとうございます。
speakerdeck.com

サンプルの仕様

ローカルの「Kinds.json」を読み込み、モデルのオブジェクトに変換し
DBに書き込む。

実行結果

このようにコンソールに表示されます。

f:id:sakura_bird1:20180123005648p:plain
f:id:sakura_bird1:20180123010744p:plain


何かおかしな部分がございましたらお声がけくださると大変ありがたいです。

関連記事
sakura-bird1.hatenablog.com




【未経験歓迎】アプリ開発、ゲーム開発、web開発、短期集中型の無料プログラミング&就活スクール

Android Studioで作成したAPKファイルをGoogle Play Consoleにリリースしようとすると「アップロードできませんでした テスト専用の APK はアップロードできません。」というエラーになる状況について

前提

Android Studio 3.0.1(2018/01/22現在)

対象のアプリは本番用アプリへの署名はbuild.gradleに設定済みで
variantを切り替えた後に、Runボタンか
Android Studio メニュー > Build > Build APK(s)を
選択するとapkがビルド出来る状態です。

状況

Android StudioでRunボタンを押して作成したAPKファイルを
Google Play Consoleにリリースしようとすると
「アップロードできませんでした テスト専用の APK はアップロードできません。」
というエラーが出てしまいました。
f:id:sakura_bird1:20180122004903p:plain:w400

このAPKファイルをadbコマンドで端末にインストールしようとすると
このようなエラーメッセージが表示されます。

adb: failed to install アプリのパス.apk:
 Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]

原因

Android Studio のバージョンが3以上ですと、
Runボタンでビルドすると「testOnly="true"」になってしまうようです。

以前はRunボタンでビルドしたapkでもリリース出来ていたのですが、
出来なくなった人がちらほら書き込んでいます↓。
android - ADB Install Fails With INSTALL_FAILED_TEST_ONLY - Stack Overflow
f:id:sakura_bird1:20180122005651p:plain

対策

メニュー > Build > Build APK(s)を
選択してAPKファイルを作成します。

又はコマンドラインから「./gradlew build」でAPKファイルを作成します。



エンジニアによるエンジニアのためのサイト始まる!!【teratail】

Gradleのバージョンを3以上に上げた時に「Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated」というエラーが発生した時の対処方法

Android StudioでGradleプラグインを2系から3.0.1にアップデートしたところ、
次のようなエラーが発生しました。

Error:(160, 0) Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.

エラーメッセージに出てくる'outputFile'というのがread-onlyプロパティなのに
書き換えようとして怒られていますね。

'outputFile'はビルドしたapkファイルの名前を書き換える処理に使っている方が多いのではないでしょうか。

Gradleは3.0.0のメジャーアップデートで色々変わったようです。
この時に仕様変更した影響によるエラーでした。

Migrate to Android Plugin for Gradle 3.0.0 | Android Studio

f:id:sakura_bird1:20180119020157p:plain

これによると、Variant APIを使用してバリアントの出力をいじるのは
apkの名前変更みたいな簡単なもの以外出来なくなったようです。
outputFileのアクセスも出来なくなったので、
公式ドキュメントのようにファイルの名前を変更する箇所を書き換える必要があります。


私のアプリの例ですが、次のように書き換えました。

変更前

def toApkFile(originalFile) {
    def namePrefix = "PocketCarbo"
    def name = originalFile.name.replace(project.name,
            namePrefix + "-v" + android.defaultConfig.versionName)
    return new File(originalFile.parentFile, name)
}

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        output.outputFile = toApkFile(output.outputFile)
        if (output.packageApplication.outputFile != output.outputFile) {
            output.packageApplication.outputFile = toApkFile(output.packageApplication.outputFile)
        }
    }
}

変更後

android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "PocketCarbo_v${android.defaultConfig.versionName}_${variant.name}.apk"
    }
}

ついでに書き方も簡略化してスッキリしましたが、
変更前、変更後のどちらもビルドすると
デバッグビルド時「PocketCarbo_v1.1_debug.apk」
リリースビルド時「PocketCarbo-v1.1-release.apk」
というような名前でapkファイルが作成されます。



エンジニアによるエンジニアのためのサイト始まる!!【teratail】

Auto Layout学習参考記事2018(iOS11、Xcode9)

はじめに

AutoLayoutを学ぶにあたって参考になったおすすめ記事や動画などの情報と
感想などを書きます。
基本的に新しいものを探してたらこのようになりました。
ちょっと古くても良い記事があるのにあまり取り上げられなくて残念でしたが、
情報を残してくださった方々に深く感謝しております。

f:id:sakura_bird1:20180117015619p:plain

前提

私はiPhoneアプリ開発を勉強しています。
チュートリアルを終え、ミニサンプルなどを作りながら学んでいる初心者です。

只今の開発環境は、iOS11、Xcode9、Swift4を使用しています。

この記事ではXcode自体に慣れていない人を対象としています。
他に良い記事に出会ったら追加していければと思っています。

Auto Layoutで泣いた

Auto Layoutは今後も増えていく画面サイズに対応していくのに欠かせない機能で、
必ず使えるようにしたいと思います。

しかしうまく設定出来なくて詰まりました。

StoryBoardの使い方自体の知識も不足している

Interface Builderで制約の設定方法の知識がない状態で
「なんとなく」「直感で」制約を追加してみたのですが、

・思ったように表示されない(笑)
・いつの間にか重複する制約を設定してしまって怒られる。
・StoryBoard左側のDocument OutlineからConstraintsをdeleteキーで全消しして
「Missing Constraints」などと怒られる。
・「Add Missing Constraints」でfixしたら余計訳がわからなくなる。
・gitの差分で.storyboardファイルの中身を見ても何をやっているのかよくわからない

などで進まなくなりました。
ろくに学習しないで出来るほど甘くなかったわけです。

学習した中で思いましたが、Auto LayoutはViewの構造が複雑になると難しいです。
思ったように表示されない部分やエラーが発生した場合、
問題のある箇所をただちに特定して解決することが出来るようになるには
試行錯誤してスキルアップするしかないのだなあと思いました。

以下ではInterface BuilderでAuto Layoutを使うための記事などを中心にご紹介します。
Apple
制約の設定には、できるだけInterface Builderを使ってください。
制約を可視化、編集、管理、デバッグするための、各種ツールが揃っています。

と言ってますし。


英語のサイトが出てきますが、私は英語が堪能でないため
Google翻訳や雰囲気でわかったつもりになっている部分が大いにあります。

実際の例を多く目にすることが出来ればいいし、
日本語サイトで知識を補えばいいのだと気軽な気持ちでやっています。
実際結構何とかなっています。

公式サイト

Auto Layoutガイド

developer.apple.com
日本語の解説です。
一次情報ですし、網羅してるし、バイブルみたいなものでしょうかね。

頑張って全部読んだほうがいいとは思いますが、
文字で読んでいると辛く感じました。

最初はもっと情報が少なく、
初心者向けに噛み砕いて説明しているものを読んだらいいと思います。

注意点(2018/01/16現在)
・top及びbottom layout guideのdeprecatedには対応していないらしく「Safe Area Layout Guide」の文字は出てこなかったです。
・「詳しくは◯◯を参照してください」と書いてあるリンクをクリックすると「Sorry, that page cannot be found.」と表示されることが多いです。

上記のこともあり、日本語版は少し情報が古いと思いますので、出来れば英語版を読むほうがいいと思います。

Auto Layout Guide(英語)

developer.apple.com

StoryBoardを使う場合

Auto Layoutガイド:Interface Builderにおける制約の操作
ここ以外はコードから設定する方法がほとんどでした。

私はこれで学習しました

初心者のためのSwiftで始めるプログラミング入門(9):初めてiPhoneアプリをデザインするには、どうすればいい?――すぐ分かるInterface Builder、Storyboard、Auto Layoutの使い方

www.atmarkit.co.jp

初心者に向けてとても優しく解説してくれています。StoryBoardを使って解説しています。
これを最初に読むのがいいのではないかと思います。
現在の私の開発環境であるXcode9とは若干異なる部分もありました(Update Framesのやり方)が、ググればすぐに出てきます。

Auto Layout Tutorial in iOS 11: Getting Started

www.raywenderlich.com

Interface Builderを使ったチュートリアルです。
英語ですがスクリーンショットも豊富で初心者の写経に向いています。
動画のチュートリアル(有料)もあるようですが見てません。

記事が作成された日が新しく、
Interface Builderに不慣れでもわかるような
スクリーンショットの多いものを探していたら
結局これを写経することになりました。

Interface Builderを使ったActionの接続の仕方を
知ってないと進めづらい箇所が一部あります。

2つのビューを同時に制約を加えたり、
マウス操作では変更できない箇所の制約の変更方法もあります。

いくつかエラーや思うように表示できない場合の解説があり
大変役に立ちました。

例えばビューの内側に配置した子ビューが複数あって
それぞれ制約を付けた場合、
親ビューのサイズが変わった時に子ビューの制約の優先度を定義しないと
AutoLayoutはそれぞれの子ビューのどちらを伸び縮みさせれば
いいか判断できずエラーになる箇所があります。
Content Hugging Priorityで優先度を指定する解決方法を紹介してくれています。

結果的にこれを写経してから急速に理解が深まってすごく良かったので、
おすすめします。

StackViewを賢く使ってらくちんAutoLayout

qiita.com
素晴らしく丁寧な説明で必読です。
出来るだけ制約を使わずにStackViewを使ってレイアウトを作ろうと思いました。
記事中の図も美しいです。

動画

動画も大いに参考になりました。
Storyboardのような画面ポチポチする系のものは動画を見ると楽です。
ご紹介する動画は英語ですが、どこをクリックすれば
目的の機能にたどり着けるか一目瞭然なので
どこに何があるのかわからない初心者のうちに見ておくとよいです。

Auto Layout Tutorial in Xcode with Swift for iOS 11 | iOS Development Tutorial

www.youtube.com
この動画では3つのサンプルを使ってAuto Layoutの効果を説明してくれています。
異なるサイズの端末プレビューを並べているのがわかりやすいです。
1時間という長さの動画ですが、参考になったので全部視聴しました。

Swift 4: Introduction to Auto Layout Programmatically (Ep 1)

www.youtube.com

Swift 4: Intro Auto Layout Landscape with Multipliers (Ep 2)

www.youtube.com
上の2つの動画では、StoryBoardでポチポチConstraintsを設定ではなく、
コードで制約を設定しています。
端末を縦→横にした時にViewの大きさを最適化するのを
AutoLayoutを使用して実現する方法を説明してくれています。
この配信者の動画は他にも視聴しましたが、やたらわかりやすいのでおすすめです。

参考になった他の資料

DevIO Auto Layout 道場スライド

https://www.slideshare.net/kakegawa-atsushi/devio-auto-layout
概要から使い方まで。前半の説明がわかりやすいです。
StoryBoard不使用。
後半のLessonは難しい感じだし、現地でセッションに参加していないとわからない部分も多いかもしれません。

Interface BuilderにおけるAuto Layoutのテクニック[WWDC 2017]

https://qiita.com/akatsuki174/items/dd055b6401a79af7ccab
WWDC2017のAuto Layout Techniques in Interface Builderのセッションのまとめ
Interface Builderを使って難しそうな画面制御を実現する技を紹介してくれています。

AutoLayoutのデバッグをする(1)

https://qiita.com/akatsuki174/items/6935bb6ff64f4df51c5a
ログの見方の他Document Outline Controlを見る、SymbolicBreakpointを使う方法などエラーを解決するために有用なデバッグ方法を書いてくれています。

Auto Layout 固有サイズに関するメモ

https://qiita.com/rooooomania/items/18a33d599714b6f94044
intrinsic content sizeって何だ?って思った時に参考にさせていただきました。

UIStackView, Storyboard Reference, CoreSpotlight API - iOS 9 bootcamp スライド

https://speakerdeck.com/kishikawakatsumi/uistackview-storyboard-reference-corespotlight-api-ios-9-bootcamp
StackViewを使いましょうというお話が前半にあります。

おすすめ本

よくわかるAuto Layout iOSレスポンシブデザインをマスター


Amazonのレビューもよく、手に入れたくなりました。
初心者向けではないというレビューもありますが、本格的に開発をやっていくなら是非手元に置きたいですね。


オンラインブートキャンプ iPhoneアプリコース



Xcode9での画像リソース追加方法(アセットカタログ・PDF)

ios アプリで使用する画像について、
・Asset Catalogで画像を追加する方法
ベクター画像を扱うためにPDF形式のファイルを使用する
の内容について書きます。

アセットカタログ(Assets Catalog)とは

アプリで使用する画像やサウンドその他リソースを管理できる便利なツールです。

異なる解像度のデバイス用の複数のサイズの画像などを管理し、
リソースを名前で呼び出すとデバイスに最適な解像度の画像を自動で使ってくれたりします。

プロジェクトを新規に作成すると、Assets.xcassetsという名前でアセットカタログが生成されます。

f:id:sakura_bird1:20180105233801p:plain

公式ドキュメント

Asset Catalog Format Reference: Format Overview

Xcodeのヘルプページ
http://help.apple.com/xcode/mac/current/#/dev10510b1f7

Added option to preserve image vector data for matching Dynamic Type scaling.
What's New in Xcode 9

アセットカタログにファイルを追加する

プロジェクトのファイルの中からAssets.xcassetsというフォルダのアイコンをクリックします。
画像ファイルをドラッグ&ドロップしてコピペするか、「+」ボタンを押して追加します。
画像追加の場合「+」ボタンから追加するなら「New Image Set」をクリックし、
1x,2x,3xのところにそれぞれの解像度の画像をドラッグ&ドロップして追加します。
png形式やjpeg形式の画像を使う場合。)

f:id:sakura_bird1:20180105235351p:plain:w300

右側のAttributes Inspectorの「Name」に指定された名前をプログラム中で使用します。

画像にPDFファイルを使用する

Xcode6から、Assets CatalogにPDFのベクター画像が使用できるようになっています。
これにより解像度別に画像を用意する必要が無くなります。

PDFをアセットカタログに追加すると、Xcodeがビルド時に@1x PNG, @2x PNG, and @3x PNGの画像ファイルを生成します。

用意するPDFファイルは@1x のサイズです。
PhotoshopIllustratorSketchInkscapePixelMatorGraphicなど様々なソフトやツールを使ってPDFファイルにエクスポート出来ます。

動的にスケールしないベクター画像(Xcode8まで)

PDFファイルを使用することで、用意する画像がワンサイズで良くなったことはいいとして、
ビルド時に生成された静的な画像ファイルでしかないので
大きなビューで画像を表示したりすると、画像は汚く表示されてしまいます。

Xcode9でAsset Catalogに「Preserve Vector Data」というオプションが追加され、PDF画像が動的にスケーリング出来るようになりました。
iOS11で実行した時に有効となるようです。

参考サイト様
Xcode 9 のベクター機能がさらなる次元に – Swift・iOSコラム – Medium
Xcode 9 Vector Images
The Unexpected Joy of Vector Images in iOS 11 — Erica Sadun

使い方はアセットカタログのAttributes InspectorのResizingのところの「Preserve Vector Data」のチェックボックスをonにするだけです。
PreviewやStoryBoardではきれいに表示されないみたいですが、実行時には綺麗に表示されます。

f:id:sakura_bird1:20180106012222p:plain:w300


以上です。



【未経験歓迎】アプリ開発、ゲーム開発、web開発、短期集中型の無料プログラミング&就活スクール