Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
63
Help us understand the problem. What is going on with this article?
@inuha

メモ帳作って初めてリリースした

作ったアプリの主な機能

(画像は開発中のものなのでリリース版と差異があります)

メモ追加

(メモのFieldでenterを押すと上部のCollectionViewに追加されて一度に登録できる)
image.png

メモ表示

image.png

長押しでメモをチェックor編集or検索

image.png

設定変更

image.png

webViewでの検索or公式アプリでの検索(safari, twitter, youtube)

image.png

なぜ作ったか

アプリ作ってリリースするという目標を立ててしまった
自分の好きなデザインのメモ帳を作ってみたかった。
学生時代に作成したメモした単語を検索するテストアプリが家族に使われていたのでリメイクしてみた。(よくあるtabeleViewのTodoリスト)

勉強になったところ

CollectionView

ほとんど使ったことがなかったのでいろいろ試してみたかった

CollectionViewの用途

横に並べてスクロールさせる

image.png

CustomCellを複数使う

CellのなかにCollectionViewを入れているのもCustomCell
image.png

TableViewっぽく使う

image.png

コンテンツサイズに合わせるCollectionView

長くなるので別途まとめる
image.png
欲を言えば縦方向の余白をつめた表示で実装したかった

PopupView

吹き出しタイプ

参考にさせてもらった記事

image.png

カスタムタイプ

吹き出しと同様にmodalPresentationStyleをcustomに設定して、必要なパラメータを設定すれば実装できる思っていたが、専用のカスタムクラスを生成して適応させる必要があった。

参考にさせてもらった記事
image.png
image.png
(タップしたセルで左右反転します)

いい感じのUIにする

メモ追加.gif

メモをまとめて登録したいので、改行で追加、タップで選択、もう一回タップで選択を外す、空欄で改行で削除など当たり前にありそうな機能を実現するのに、ロジックを組み合わせる必要があって地味に大変だった。

ダークモード対応

ver1.3以降
ColorAssetのみでUIの色を構成してダークモード対応できる予定だった。

Color.xcassets
image.png

xib(おそらくstoryboardも)で色を定義していた場合アプリ起動中でも動的に切り替わる。
しかしViewDidLoadの内部などでコードで色を指定する場合、アプリ起動中にモードを変更すると反映されない。
このアプリでは角丸の枠線はコードで生成しているため枠だけ色が変わらないという状態になった。
image.png

下記のようにモードが変更されたときの通知を受け取って対応する。
参考にさせてもらった記事
ViewDidLoad内で色を設定しているだけならself.viewDidLoad()だけでOK
今回はCollectionViewを再描画したかったのでself.loadView()も呼んでいる。
(ViewDidLoadだとセルが使いまわされてしまう?)

VC

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        self.loadView()
        self.viewDidLoad()
    }

便利なExtension

下記公開されているものにとてもお世話になりました。
使うと手放せなくなるSwift Extension集 (Swift 4版)
Rectの中心をとるextension

Realm

タグ名でプライマリーキーで登録しようとしていたが同じ値を再び登録できないことに気づかずハマった。
プライマリーキーの使い方で下記記事がとても参考になった。
参考にさせてもらった記事

RealmObject
  final class TagData: Object {
     @objc dynamic var id: String = NSUUID().uuidString

     override static func primaryKey() -> String? {
         "id"
     }
 }

Realmに限らないと思われるが、Xcode12でpod installした時にシミュレータでビルドできなくなって困った。実機ではビルドできる。
参考にした回答
DebugBuild時だけ解決。Releaseはエラーが出てうまくいかない(心が折れて調査してない)

RealmのBuild Setting
image.png

fastlane

いろんなサイトを見て導入。increment_build_numberとuploadだけしか実施できてない。。
Archive~UploadまでするときにXcodeを占領しないので便利。
Upload時に正しくモジュールが生成できたか確認したいときはGUIで見たかったので、アーキテクチャに変更を加える際は、Xcodeで手動で行う方が良さそう。

アーキテクチャについて

image.png
ざっくりとした役割
view: 表示、遷移
presenter: viewからの通知を受け取ってModel層から値を受け取る中間的な役割
Domain: ビジネスロジック担当。
Infra: Realmからの値取得などコアロジック担当
Utility: 共通で使いたい型、extensionを持っている。

Domain <- Infraという依存関係にすることによってInfraの実態を知らなくてもPresenterに値を返せるのでテスト時にモックに置き換えできたりする。

Embedded Frameworkのuploadについて

上記のような構成でframeworkを分けて開発していたのだが、モジュールupload時にエラーが出てしまった。
エラーについて

うまくまとめられなかった実装

popupViewのカスタムクラスに値を渡す

popupViewのカスタムクラスに座標を渡したかったのだか、delegateでカスタムクラスを返しているため、セル長押し時に座標を直接渡すという微妙な実装になった。

微妙な実装
//長押し処理の中
let customPresentationController = buttonViewController.presentationController as! CustomPresentationController
customPresentationController.rect = memoCollectionView.nowPosition(cell: cell)

delegateまみれになったview

後先考えずに画面を増やした結果delegateでfatになったVCになってしまった。
図のViewのdelegateに加えてcollectionView、presenterのdelegateもある。
コードを見るモチベが下がりクソコードがそのままになっているという悪循環が生まれている。
image.png

Model内の依存関係

DomainとInfraでメモとタグに関わるロジックを分けていたが、
タグを削除する際にタグに紐づくメモを削除することとなり、DomainのタグにメモのInfraを外部注入することとなった。。presenter側でタグに紐づくメモを削除する関係を作るのは好ましくないと思ったのでこうなったが、もっといい方法がないか...
image.png

statusbarの高さを取る処理でdeprecatedの処理を使ってしまった

ボタン長押しで表示するviewの中心座標を求める処理
        presentedViewFrame.center.y = rect.center.y + UIApplication.shared.statusBarFrame.height

感想

初めてアプリ作成でリリースまでを行ないました。AppleStoreに載ってしまうのもあってUIの方に注力して手一杯になってしまいました。(本来はAPIとかRx、Combineとかも勉強しないといけなかった。。)
その分UI周りの実装で理解が深まったのとUpload時にエラーが出たときなどBuildSettingとか弄る機会があったので、アプリの設定周りも少しだけ理解が深まった気がします。
開発時間が基本深夜なのもあってスペルミスとか結構出てしまった。swift lintとかスペルチェックするツールを導入しておけばよかったなと思います。。

63
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
inuha

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
63
Help us understand the problem. What is going on with this article?