20191127のiOSに関する記事は15件です。

Xcode外で追加したXcodeプロジェクト内のファイルをXcodeに認識させる

Xcode外で追加したファイルはXcodeに認識されないことがよくあります。

例えば、

  • Firebaseに必要なGoogleService-Info.plistをFinderで追加した
  • 画像ファイルをFinderで追加した
  • xcconfigを外部エディタで作成した

など・・・。

そのような場合は、Xcode でドラッグ&ドロップして追加することで問題なく認識されます。
このとき、Copy items if neededにはチェックをいてておきましょう。
(その場所に同じファイルがなければコピーして作ってくれます。もしない場合にチェックしていなければ、選択したものを直接参照するようになります)
image.png

たまーにGoogleService-Info.plistをXcodeが認識してなくてFirebaseがエラー※1を吐いちゃってるけど、
なぜエラーがおきてるかわからないという人がよくいたので記事にしてみました。

※1: Could not locate configuration file: ‘GoogleService-Info.plist’.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

flutterでpodfile関係でビルド出来ないとき

以下のエラーになってビルドにこけた

error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.

該当のプロジェクトのios配下で pod install して再度ビルドしたらいけた?‍♀️

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

一人でVIPERアーキテクチャーでiOSスマホアプリ開発した感想

ここ最近、フルスクラッチのiOSアプリ開発でVIPERアーキテクチャを使用して、開発したので、感想を書いてみます。

はじめに

開発期間が3ヶ月ほどのiOS新規開発アプリで、Swift VIPERアーキテクチャを使用したアプリを開発しました。
途中まで、シンプルなMVCで作成していましたが、いまいちだったのでVIPERを気まぐれで採用した感じです。

いきなり結果ですが、見通しがよく、改修しやすい、品質の高いアプリを実装出来たので、今後も新規開発で採用していこうと思ってます!
あとは、そろそろ誰がガチガチのiOSのフレームワークを作ってくれないかなーと

参考にした資料

VIPERを使って特によかったところ

  • 理解と導入が楽(Clean Architecture / MVVMと比べて)
  • 他のアーキテクチャと比べて、良い意味で奥が深くないと思うので、気楽に導入できる
    (MVC、MVVMは毎回色々悩むので)
  • 慣れると、流れ作業で画面を量産できる
  • 適当に作っても、ルールにしたがっていればそれなりに綺麗にできる
    (ロジックをInteractorにぶち込む)
  • 他の案件に使いまわせる実装がかなり多いイメージ
  • ViewController内に、画面遷移のコードを書かなくて良いのがすごくかっこいい
  • ロジック、WebAPIの仕様変更があっても、ViewControllerまで変更が入ることが少なかった

メリット詳細

  • プロジェクト構成を悩まなくて良い
  • MVCで開発する速度と、慣れさえすれば変わらないと思う
  • ViewControllerを徹底的に軽くできる
  • APIの仕様変更時に、ViewControllerを変更しなくて良い確率が上がる
  • 途中まで、MVCで作っていた物を、さほど苦戦せずにVIPERに変更できた
  • MVVMとは違い、ロジックの処理をまとめやすい
  • 開発が進むにつれて、開発速度をどんどん上げることが出来た
  • 開発が進んでも一定の品質を簡単に保てた
  • 複数人開発の時に、基準ができるので無駄な争いが起きなそう
  • 各階層ごとの役割が明快なので、コードレビューもしやすいはず
  • エラー表示処理や、インジゲータ表示処理などをViewControllerのExtensionにまとめると、使いまわしがすごくしやすい
  • 無駄な条件分岐の実装が極端に減った
  • プログラム内のネストが極端に減った
  • 多分、UTもしやすいはず(そんな工数はもらってないので、やってない)

デメリット詳細

MVCと比べて、開発速度が下がると行ったこともほとんどないので、デメリットはほとんど無しです。

  • 開発の初期は、プロジェクトの構成作りに悩んでしまったので、時間を浪費した
  • 当たり前だが、引き継ぎ時にアーキテクチャを相手に理解してもらう必要が出てきた
  • 日本では、RxSwiftを使ったMVVMの方が流行ってるイメージ

悩んだところ

  • 色々なサンプルをみたが、割とみんなバラバラなプロジェクト構成、作りになっている
    -> PHPのフレームワークのようにガチガチな規約があると考えなくて助かるのになぁと
  • Interactorを使い回す時の取り回し
    -> DIする時にまとめて渡す方式にした
  • Protocolの置き場所
    -> モジュールごとに1ファイルにまとめた
  • View -> Presenter部分のメソッド名の付け方
    -> 結局アクション名でつけた 例)didPushHoge, didSelectHoge

失敗したところ

  • ViewControllerに少しロジックが乗ってしまった
  • 前の画面に戻る遷移は、全RouterにInterfaceでつければよかった
  • モジュールの自動作成をできるようにすれば、もっと工数を下げれた

次回以降、気をつけたいところ、やりたいこと

  • 公開できるレベルの実際に動作するサンプルPJを作りたい
  • VIPER + Rxでいい感じになるかも
  • View -> Presenter部分のメソッド名の付け方を再考する
  • モジュールのテンプレをコマンドで作成できるようにする
  • RouterのViewController生成部分でNavigationControllerを渡したのはよくない

おまけ(似たようなアーキテクチャ感想記事)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

一人でVIPERアーキテクチャーでiOSスマホアプリ開発した感想 まとめ

ここ最近、フルスクラッチのiOSアプリ開発でVIPERアーキテクチャを使用して、開発したので、感想を書いてみます。

はじめに

開発期間が3ヶ月ほどのiOS新規開発アプリで、Swift VIPERアーキテクチャを使用したアプリを開発しました。
途中まで、シンプルなMVCで作成していましたが、いまいちだったのでVIPERを気まぐれで採用した感じです。

いきなり結果ですが、見通しがよく、改修しやすい、品質の高いアプリを実装出来たので、今後も新規開発で採用していこうと思ってます!
あとは、そろそろ誰がガチガチのiOSのフレームワークを作ってくれないかなーと

参考にした資料

VIPERを使って特によかったところ

  • 理解と導入が楽(Clean Architecture / MVVMと比べて)
  • 他のアーキテクチャと比べて、良い意味で奥が深くないと思うので、気楽に導入できる
    (MVC、MVVMは毎回色々悩むので)
  • 慣れると、流れ作業で画面を量産できる
  • 適当に作っても、ルールにしたがっていればそれなりに綺麗にできる
    (ロジックをInteractorにぶち込む)
  • 他の案件に使いまわせる実装がかなり多いイメージ
  • ViewController内に、画面遷移のコードを書かなくて良いのがすごくかっこいい
  • ロジック、WebAPIの仕様変更があっても、ViewControllerまで変更が入ることが少なかった

メリット詳細

  • プロジェクト構成を悩まなくて良い
  • MVCで開発する速度と、慣れさえすれば変わらないと思う
  • ViewControllerを徹底的に軽くできる
  • APIの仕様変更時に、ViewControllerを変更しなくて良い確率が上がる
  • 途中まで、MVCで作っていた物を、さほど苦戦せずにVIPERに変更できた
  • MVVMとは違い、ロジックの処理をまとめやすい
  • 開発が進むにつれて、開発速度をどんどん上げることが出来た
  • 開発が進んでも一定の品質を簡単に保てた
  • 複数人開発の時に、基準ができるので無駄な争いが起きなそう
  • 各階層ごとの役割が明快なので、コードレビューもしやすいはず
  • エラー表示処理や、インジゲータ表示処理などをViewControllerのExtensionにまとめると、使いまわしがすごくしやすい
  • 無駄な条件分岐の実装が極端に減った
  • プログラム内のネストが極端に減った
  • 多分、UTもしやすいはず(そんな工数はもらってないので、やってない)

デメリット詳細

MVCと比べて、開発速度が下がると行ったこともほとんどないので、デメリットはほとんど無しです。

  • 開発の初期は、プロジェクトの構成作りに悩んでしまったので、時間を浪費した
  • 当たり前だが、引き継ぎ時にアーキテクチャを相手に理解してもらう必要が出てきた
  • 日本では、RxSwiftを使ったMVVMの方が流行ってるイメージ

悩んだところ

  • 色々なサンプルをみたが、割とみんなバラバラなプロジェクト構成、作りになっている
    -> PHPのフレームワークのようにガチガチな規約があると考えなくて助かるのになぁと
  • Interactorを使い回す時の取り回し
    -> DIする時にまとめて渡す方式にした
  • Protocolの置き場所
    -> モジュールごとに1ファイルにまとめた
  • View -> Presenter部分のメソッド名の付け方
    -> 結局アクション名でつけた 例)didPushHoge, didSelectHoge

失敗したところ

  • ViewControllerに少しロジックが乗ってしまった
  • 前の画面に戻る遷移は、全RouterにInterfaceでつければよかった
  • モジュールの自動作成をできるようにすれば、もっと工数を下げれた

次回以降、気をつけたいところ、やりたいこと

  • 公開できるレベルの実際に動作するサンプルPJを作りたい
  • VIPER + Rxでいい感じになるかも
  • View -> Presenter部分のメソッド名の付け方を再考する
  • モジュールのテンプレをコマンドで作成できるようにする
  • RouterのViewController生成部分でNavigationControllerを渡したのはよくない

おまけ(似たようなアーキテクチャ感想記事)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DelegateProxy の Observable にイベントが飛んでこないケースがあった

RxSwift (RxCocoa) には、標準ライブラリの主要な delegate メッセージに対応する Observable が用意されています。DelegateProxy という仕組みです。

今回、その中で UISearchControllerDelegate の各デリゲートメソッドを、RxSwift を用いて非同期的に扱いたかったのですが、ハマったのでまとめておきます。

うまくいかないパターン

class TheViewController: UIViewController, UISearchControllerDelegate {

    var searchController = UISearchController()
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        searchController.delegate = self

        // 1
        searchController.rx.willPresent.subscribe(onNext: { _ in
            /** これが呼ばれない **/
        }).disposed(by: disposeBag)
    }

    // 2
    func willPresentSearchController(_ searchController: UISearchController) {
        /** こっちは呼ばれる ***/
    }
}

上記の例では、UISearchControllerDelegate を、TheViewController 自身にセットして、willPresentSearchController を実装していますが、同時に RxSwift を使って willPresentSearchController の Observable 変数である willPresent に何らかの処理を非同期で行おうとしています。

こうすると、willPresent を subscribe しても実際にここにイベントが飛んでくることはありませんでした。

1 と 2 は同じタイミングで発火するものですが、delegate が viewController にセットされていることで 2 が優先されているといった状況になっているようです。

===
※ 実際には1つのクラス内でこんな妙な実装をすることはなく、プロトコルなどを使ってデリゲートの宣言や共通処理を切り出していたりするので、この問題のパターンになっていることに気付きませんでした。

うまくいくパターン

class TheViewController: UIViewController {

    var searchController = UISearchController()
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1
        searchController.rx.willPresent.subscribe(onNext: { _ in
            /** 呼ばれる **/
        }).disposed(by: disposeBag)
    }
}

上記サンプルを見れば当たり前なのですが...

RxSwift の DelegateProxy で与えられる Observable を購読して非同期で処理したい場合は、それに集約する必要があります。つまり UIViewControllerDelegate を ViewController に指定して、デリゲートメソッドを実装する方法を同時に行わないということです。

親にあたるクラスやプロトコルでデリゲートが実装されていると、末端のクラスでこのように RxSwift の DelegateProxy 経由の Observable が飛んでこないことがあります。
ソースコードが大規模になってくるとプロトコルや継承によって見通しが悪くなると起こりやすいので、気を付ける必要がありそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

私がアプリ開発のSESで、面談時に地雷案件をなるべく避けるための確認ポイント7選

私は、客先常駐でアプリを開発、保守するのをメインに5年ほどお仕事してきました。
iOSとAndroidのどちらかを担当して、機能やスケジュールの提案をしつつ、もくもくと開発していることが多いエンジニアです。

常駐のため、現場が変わるごとに面談があり(法律なんか知らん)、その度にやばそうな雰囲気の出てる案件は基本的に避けるようにしています。
現場に入る前の面談で、これを確認すれば、地雷案件を少し回避できるポイントがなんとなくわかってきたので、メモっておきます。
※あくまで個人的な指標であって、なんの根拠もないです!!

保守案件の場合は、アプリのストア評価を確認

保守案件で、ストアの評価が低いアプリは可能な限り参画を回避します。

理由は、

  • ストアの評価が低いものは、内部の品質が基本的に低い
  • 新たな開発はできずに、既存バグの修正に追われて疲弊する
  • ただのバグ修正ではスキルがつきにくい
  • クソコードを見ると発狂する(コントローラにAPIリクエストが入っているとか無理)
  • ひどい場合、gitすら使ってない
  • その他色々

だからです。
何より、過去に低評価アプリを3つほど、保守・機能追加を担当して、すごく苦労したので

アプリのアーキテクチャーを確認

  • 全てをControllerに実装するアーキテクチャ
  • MVC
  • MVVM
  • VIPER
  • CleanArchitecture
  • など

色々とありますが、開発するアプリのアーキテクチャが決まっている場合があるので、確認します。

保守開発の案件で、既存のアーキテクチャを教えていただけることがあるのですが、
なぜか「CleanArchitecture」を使用してると言われるプロジェクトは、クラス名だけCleanArchitectureで、中身はぐちゃぐちゃの地雷が多いです。

経験上、「CleanArchitecture」と「全てをControllerに実装するアーキテクチャ」は避けたい対象となっています。

常駐先の会社さんにアプリ開発をできるプロパーさんがいるか確認

受託開発の新規作成案件で、アプリを開発できるエンジニアさんがいない会社が受けた場合、要件定義や見積もりでやらかしている可能性がかなり上がります。
Web画面を作る感覚でアプリの見積もりをしてしまった案件の場合は、開発工数がそもそも足りていない場合が多くあるイメージです。

見積もりが多い分には、常駐する側としては問題ないのでが、やらかしている可能性が高い案件の場合が多いので、なるべく避けるのがおすすめです。

開発者を複数人募集している案件は、他のメンバーのスキルを確認

最近の案件は、1アプリを2~3人くらいで新規開発をする案件がそこそこあるイメージです。
ただし、複数人開発と言えど、

  • 新人さん(2年未満)
  • アプリを一人で作ったことのない人

が相方として参画しそうな場合は、申し訳ないですが確実に避けるようにしています。
(他の人の面倒を見るのは避けたい。ただし、面倒を見る費用をもらえる場合は別途相談)

また、開発規模の割に人数が多い案件の場合は、
スキルの低い人間を集めて、クライアントへの見積もりをカサ増ししている案件が多いです。
(できる人が1人で2ヶ月できるのを、4人で半年とか)
結局、できる人間が全て作るハメになるので、避けるようにしています。

フロアのエンジニアの残業状況を確認

面談の際に常駐先のエンジニアの残業状態を確認します。
残業をしている人が多い場合は、だらだら仕事する癖がついている or 仕事量がおかしい 現場の可能性が高いので、なるべく避けます。

質問は、自分から質問すると残業を避けたがるエンジニアのイメージがつく気がするので、営業から質問してもらえるようにお願いするのがベストです。

スクラム開発の場合に、スクラムの前提を満たしているか確認

最近流行っているスクラム開発を取り入れている案件がそこそこ出てきました。
ただし、スクラムをやる上で、前提条件を満たしていない案件が多いので注意が必要です。

  • 全機機能ができる納期がある????
  • スキルがバラバラすぎる
  • クライアントがスクラム開発に乗り気ではない(POさんがいないとか)
  • スクラムを銀の弾丸と思っている人がいる(スクラムだから開発に成功するとか)

(前提条件を満たしていない時点で、スクラムではないと思いますが。。。)

また、これは個人的な都合ですが、以下の点でスクラム開発はちょっとやりにくいところがあります。

  • 作業見積もりをごまかしにくい
  • 最初に一気に開発して、開発期間の最後の方でゆっくりすることがしにくい(開発期間の余ったところでだらだらするのが趣味のため)
  • 全員バラバラの所属で、ガッチリとしたチームプレーはちょっとめんどい

色々、ネガティブなことを書いてますが、うまくはまっているスクラム開発は色々と新しいことができて楽しいのでおすすめです!!

開発環境の確認

  • Mac/PCの簡単なスペック(メモリ8GBじゃ辛い)
  • iPhoneなどの実機の有無

などを念の為確認すると、あとで開発中にイライラするのを防げるかもしれないです。

まとめ

色々書きましたが、結局は現場に参画してみないとわかりません。

わざわざ、大変だったり辛い現場に行くのは勿体無いので、
お金をもらえながら、楽しくてスキルのつける現場になるべく行けるように、これからも頑張って面談していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iOS/Androidアプリ開発のSESで、面談時に地雷案件をなるべく避けるための確認ポイント7選

私は、客先常駐でアプリを開発、保守するのをメインに5年ほどお仕事してきました。
iOSとAndroidのどちらかを担当して、機能やスケジュールの提案をしつつ、もくもくと開発していることが多いエンジニアです。

常駐のため、現場が変わるごとに面談があり(法律なんか知らん)、その度にやばそうな雰囲気の出てる案件は基本的に避けるようにしています。
現場に入る前の面談で、これを確認すれば、地雷案件を少し回避できるポイントがなんとなくわかってきたので、メモっておきます。
※あくまで個人的な指標であって、なんの根拠もないです!!

保守案件の場合は、アプリのストア評価を確認

保守案件で、ストアの評価が低いアプリは可能な限り参画を回避します。

理由は、

  • ストアの評価が低いものは、内部の品質が基本的に低い
  • 新たな開発はできずに、既存バグの修正に追われて疲弊する
  • ただのバグ修正ではスキルがつきにくい
  • クソコードを見ると発狂する(コントローラにAPIリクエストが入っているとか無理)
  • ひどい場合、gitすら使ってない
  • その他色々

だからです。
何より、過去に低評価アプリを3つほど、保守・機能追加を担当して、すごく苦労したので

アプリのアーキテクチャーを確認

  • 全てをControllerに実装するアーキテクチャ
  • MVC
  • MVVM
  • VIPER
  • CleanArchitecture
  • など

色々とありますが、開発するアプリのアーキテクチャが決まっている場合があるので、確認します。

保守開発の案件で、既存のアーキテクチャを教えていただけることがあるのですが、
なぜか「CleanArchitecture」を使用してると言われるプロジェクトは、クラス名だけCleanArchitectureで、中身はぐちゃぐちゃの地雷が多いです。

経験上、「CleanArchitecture」と「全てをControllerに実装するアーキテクチャ」は避けたい対象となっています。

常駐先の会社さんにアプリ開発をできるプロパーさんがいるか確認

受託開発の新規作成案件で、アプリを開発できるエンジニアさんがいない会社が受けた場合、要件定義や見積もりでやらかしている可能性がかなり上がります。
Web画面を作る感覚でアプリの見積もりをしてしまった案件の場合は、開発工数がそもそも足りていない場合が多くあるイメージです。

見積もりが多い分には、常駐する側としては問題ないのでが、やらかしている可能性が高い案件の場合が多いので、なるべく避けるのがおすすめです。

開発者を複数人募集している案件は、他のメンバーのスキルを確認

最近の案件は、1アプリを2~3人くらいで新規開発をする案件がそこそこあるイメージです。
ただし、複数人開発と言えど、

  • 新人さん(2年未満)
  • アプリを一人で作ったことのない人

が相方として参画しそうな場合は、申し訳ないですが確実に避けるようにしています。
(他の人の面倒を見るのは避けたい。ただし、面倒を見る費用をもらえる場合は別途相談)

また、開発規模の割に人数が多い案件の場合は、
スキルの低い人間を集めて、クライアントへの見積もりをカサ増ししている案件が多いです。
(できる人が1人で2ヶ月できるのを、4人で半年とか)
結局、できる人間が全て作るハメになるので、避けるようにしています。

SIer系は避ける

会社さんによりますが、古いルールとかに縛られていることがあるので、近づかないほうがいいイメージ。
特にスーツ必須のところは、ちょっと怖い。
※うちは、違うぜ!だ感じの会社さんはごめんなさい。経験上は、どうしても多いのです。

フロアのエンジニアの残業状況を確認

面談の際に常駐先のエンジニアの残業状態を確認します。
残業をしている人が多い場合は、だらだら仕事する癖がついている or 仕事量がおかしい 現場の可能性が高いので、なるべく避けます。

質問は、自分から質問すると残業を避けたがるエンジニアのイメージがつく気がするので、営業から質問してもらえるようにお願いするのがベストです。

スクラム開発の場合に、スクラムの前提を満たしているか確認

最近流行っているスクラム開発を取り入れている案件がそこそこ出てきました。
ただし、スクラムをやる上で、前提条件を満たしていない案件が多いので注意が必要です。

  • 全機能ができる納期がある????
  • スキルがバラバラすぎる
  • クライアントがスクラム開発に乗り気ではない(POさんがいないとか)
  • スクラムを銀の弾丸と思っている人がいる(スクラムだから開発に成功するとか)

(前提条件を満たしていない時点で、スクラムではないと思いますが。。。)

また、これは個人的な都合ですが、以下の点でスクラム開発はちょっとやりにくいところがあります。

  • 作業見積もりをごまかしにくい
  • 最初に一気に開発して、開発期間の最後の方でゆっくりすることがしにくい(開発期間の余ったところでだらだらするのが趣味のため)
  • 全員バラバラの所属で、ガッチリとしたチームプレーはちょっとめんどい

色々、ネガティブなことを書いてますが、うまくはまっているスクラム開発は色々と新しいことができて楽しいのでおすすめです!!

開発環境の確認

  • Mac/PCの簡単なスペック(メモリ8GBじゃ辛い)
  • iPhoneなどの実機の有無

などを念の為確認すると、あとで開発中にイライラするのを防げるかもしれないです。

まとめ

色々書きましたが、結局は現場に参画してみないとわかりません。

わざわざ、大変だったり辛い現場に行くのは勿体無いので、
お金をもらえながら、楽しくてスキルのつける現場になるべく行けるように、これからも頑張って面談していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

私がiOS/Androidアプリ開発のSESで、面談時に地雷案件をなるべく避けるための確認ポイント7選

私は、客先常駐でアプリを開発、保守するのをメインに5年ほどお仕事してきました。
iOSとAndroidのどちらかを担当して、機能やスケジュールの提案をしつつ、もくもくと開発していることが多いエンジニアです。

常駐のため、現場が変わるごとに面談があり(法律なんか知らん)、その度にやばそうな雰囲気の出てる案件は基本的に避けるようにしています。
現場に入る前の面談で、これを確認すれば、地雷案件を少し回避できるポイントがなんとなくわかってきたので、メモっておきます。
※あくまで個人的な指標であって、なんの根拠もないです!!

保守案件の場合は、アプリのストア評価を確認

保守案件で、ストアの評価が低いアプリは可能な限り参画を回避します。

理由は、

  • ストアの評価が低いものは、内部の品質が基本的に低い
  • 新たな開発はできずに、既存バグの修正に追われて疲弊する
  • ただのバグ修正ではスキルがつきにくい
  • クソコードを見ると発狂する(コントローラにAPIリクエストが入っているとか無理)
  • ひどい場合、gitすら使ってない
  • その他色々

だからです。
何より、過去に低評価アプリを3つほど、保守・機能追加を担当して、すごく苦労したので

アプリのアーキテクチャーを確認

  • 全てをControllerに実装するアーキテクチャ
  • MVC
  • MVVM
  • VIPER
  • CleanArchitecture
  • など

色々とありますが、開発するアプリのアーキテクチャが決まっている場合があるので、確認します。

保守開発の案件で、既存のアーキテクチャを教えていただけることがあるのですが、
なぜか「CleanArchitecture」を使用してると言われるプロジェクトは、クラス名だけCleanArchitectureで、中身はぐちゃぐちゃの地雷が多いです。

経験上、「CleanArchitecture」と「全てをControllerに実装するアーキテクチャ」は避けたい対象となっています。

常駐先の会社さんにアプリ開発をできるプロパーさんがいるか確認

受託開発の新規作成案件で、アプリを開発できるエンジニアさんがいない会社が受けた場合、要件定義や見積もりでやらかしている可能性がかなり上がります。
Web画面を作る感覚でアプリの見積もりをしてしまった案件の場合は、開発工数がそもそも足りていない場合が多くあるイメージです。

見積もりが多い分には、常駐する側としては問題ないのでが、やらかしている可能性が高い案件の場合が多いので、なるべく避けるのがおすすめです。

開発者を複数人募集している案件は、他のメンバーのスキルを確認

最近の案件は、1アプリを2~3人くらいで新規開発をする案件がそこそこあるイメージです。
ただし、複数人開発と言えど、

  • 新人さん(2年未満)
  • アプリを一人で作ったことのない人

が相方として参画しそうな場合は、申し訳ないですが確実に避けるようにしています。
(他の人の面倒を見るのは避けたい。ただし、面倒を見る費用をもらえる場合は別途相談)

また、開発規模の割に人数が多い案件の場合は、
スキルの低い人間を集めて、クライアントへの見積もりをカサ増ししている案件が多いです。
(できる人が1人で2ヶ月できるのを、4人で半年とか)
結局、できる人間が全て作るハメになるので、避けるようにしています。

SIer系は避ける

会社さんによりますが、古いルールとかに縛られていることがあるので、近づかないほうがいいイメージ。
特にスーツ必須のところは、ちょっと怖い。
※うちは、違うぜ!だ感じの会社さんはごめんなさい。経験上は、どうしても多いのです。

フロアのエンジニアの残業状況を確認

面談の際に常駐先のエンジニアの残業状態を確認します。
残業をしている人が多い場合は、だらだら仕事する癖がついている or 仕事量がおかしい 現場の可能性が高いので、なるべく避けます。

質問は、自分から質問すると残業を避けたがるエンジニアのイメージがつく気がするので、営業から質問してもらえるようにお願いするのがベストです。

スクラム開発の場合に、スクラムの前提を満たしているか確認

最近流行っているスクラム開発を取り入れている案件がそこそこ出てきました。
ただし、スクラムをやる上で、前提条件を満たしていない案件が多いので注意が必要です。

  • 全機能ができる納期がある????
  • スキルがバラバラすぎる
  • クライアントがスクラム開発に乗り気ではない(POさんがいないとか)
  • スクラムを銀の弾丸と思っている人がいる(スクラムだから開発に成功するとか)

(前提条件を満たしていない時点で、スクラムではないと思いますが。。。)

また、これは個人的な都合ですが、以下の点でスクラム開発はちょっとやりにくいところがあります。

  • 作業見積もりをごまかしにくい
  • 最初に一気に開発して、開発期間の最後の方でゆっくりすることがしにくい(開発期間の余ったところでだらだらするのが趣味のため)
  • 全員バラバラの所属で、ガッチリとしたチームプレーはちょっとめんどい

色々、ネガティブなことを書いてますが、うまくはまっているスクラム開発は色々と新しいことができて楽しいのでおすすめです!!

開発環境の確認

  • Mac/PCの簡単なスペック(メモリ8GBじゃ辛い)
  • iPhoneなどの実機の有無

などを念の為確認すると、あとで開発中にイライラするのを防げるかもしれないです。

まとめ

色々書きましたが、結局は現場に参画してみないとわかりません。

わざわざ、大変だったり辛い現場に行くのは勿体無いので、
お金をもらえながら、楽しくてスキルのつける現場になるべく行けるように、これからも頑張って面談していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SESで、面談時に地雷案件をなるべく避けるための確認ポイント7選(iOS/Androidアプリ開発)

私は、客先常駐でアプリを開発、保守するのをメインに5年ほどお仕事してきました。
iOSとAndroidのどちらかを担当して、機能やスケジュールの提案をしつつ、もくもくと開発していることが多いエンジニアです。

常駐のため、現場が変わるごとに面談があり(法律なんか知らん)、その度にやばそうな雰囲気の出てる案件は基本的に避けるようにしています。
現場に入る前の面談で、これを確認すれば、地雷案件を少し回避できるポイントがなんとなくわかってきたので、メモっておきます。
※あくまで個人的な指標であって、なんの根拠もないです!!

保守案件の場合は、アプリのストア評価を確認

保守案件で、ストアの評価が低いアプリは可能な限り参画を回避します。

理由は、

  • ストアの評価が低いものは、内部の品質が基本的に低い
  • 新たな開発はできずに、既存バグの修正に追われて疲弊する
  • ただのバグ修正ではスキルがつきにくい
  • クソコードを見ると発狂する(コントローラにAPIリクエストが入っているとか無理)
  • ひどい場合、gitすら使ってない
  • その他色々

だからです。
何より、過去に低評価アプリを3つほど、保守・機能追加を担当して、すごく苦労したので

アプリのアーキテクチャーを確認

  • 全てをControllerに実装するアーキテクチャ
  • MVC
  • MVVM
  • VIPER
  • CleanArchitecture
  • など

色々とありますが、開発するアプリのアーキテクチャが決まっている場合があるので、確認します。

保守開発の案件で、既存のアーキテクチャを教えていただけることがあるのですが、
なぜか「CleanArchitecture」を使用してると言われるプロジェクトは、クラス名だけCleanArchitectureで、中身はぐちゃぐちゃの地雷が多いです。

経験上、「CleanArchitecture」と「全てをControllerに実装するアーキテクチャ」は避けたい対象となっています。

常駐先の会社さんにアプリ開発をできるプロパーさんがいるか確認

受託開発の新規作成案件で、アプリを開発できるエンジニアさんがいない会社が受けた場合、要件定義や見積もりでやらかしている可能性がかなり上がります。
Web画面を作る感覚でアプリの見積もりをしてしまった案件の場合は、開発工数がそもそも足りていない場合が多くあるイメージです。

見積もりが多い分には、常駐する側としては問題ないのでが、やらかしている可能性が高い案件の場合が多いので、なるべく避けるのがおすすめです。

開発者を複数人募集している案件は、他のメンバーのスキルを確認

最近の案件は、1アプリを2~3人くらいで新規開発をする案件がそこそこあるイメージです。
ただし、複数人開発と言えど、

  • 新人さん(2年未満)
  • アプリを一人で作ったことのない人

が相方として参画しそうな場合は、申し訳ないですが確実に避けるようにしています。
(他の人の面倒を見るのは避けたい。ただし、面倒を見る費用をもらえる場合は別途相談)

また、開発規模の割に人数が多い案件の場合は、
スキルの低い人間を集めて、クライアントへの見積もりをカサ増ししている案件が多いです。
(できる人が1人で2ヶ月できるのを、4人で半年とか)
結局、できる人間が全て作るハメになるので、避けるようにしています。

SIer系は避ける

会社さんによりますが、古いルールとかに縛られていることがあるので、近づかないほうがいいイメージ。
特にスーツ必須のところは、ちょっと怖い。
※うちは、違うぜ!だ感じの会社さんはごめんなさい。経験上は、どうしても多いのです。

フロアのエンジニアの残業状況を確認

面談の際に常駐先のエンジニアの残業状態を確認します。
残業をしている人が多い場合は、だらだら仕事する癖がついている or 仕事量がおかしい 現場の可能性が高いので、なるべく避けます。

質問は、自分から質問すると残業を避けたがるエンジニアのイメージがつく気がするので、営業から質問してもらえるようにお願いするのがベストです。

スクラム開発の場合に、スクラムの前提を満たしているか確認

最近流行っているスクラム開発を取り入れている案件がそこそこ出てきました。
ただし、スクラムをやる上で、前提条件を満たしていない案件が多いので注意が必要です。

  • 全機能ができる納期がある????
  • スキルがバラバラすぎる
  • クライアントがスクラム開発に乗り気ではない(POさんがいないとか)
  • スクラムを銀の弾丸と思っている人がいる(スクラムだから開発に成功するとか)

(前提条件を満たしていない時点で、スクラムではないと思いますが。。。)

また、これは個人的な都合ですが、以下の点でスクラム開発はちょっとやりにくいところがあります。

  • 作業見積もりをごまかしにくい
  • 最初に一気に開発して、開発期間の最後の方でゆっくりすることがしにくい(開発期間の余ったところでだらだらするのが趣味のため)
  • 全員バラバラの所属で、ガッチリとしたチームプレーはちょっとめんどい

色々、ネガティブなことを書いてますが、うまくはまっているスクラム開発は色々と新しいことができて楽しいのでおすすめです!!

開発環境の確認

  • Mac/PCの簡単なスペック(メモリ8GBじゃ辛い)
  • iPhoneなどの実機の有無

などを念の為確認すると、あとで開発中にイライラするのを防げるかもしれないです。

まとめ

色々書きましたが、結局は現場に参画してみないとわかりません。

わざわざ、大変だったり辛い現場に行くのは勿体無いので、
お金をもらえながら、楽しくてスキルのつける現場になるべく行けるように、これからも頑張って面談していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SES】ドナドナされる時の面談時に地雷案件をなるべく避けるための確認ポイント7選(iOS/Androidアプリ開発)

私は、客先常駐でアプリを開発、保守するのをメインに5年ほどお仕事してきました。
iOSとAndroidのどちらかを担当して、機能やスケジュールの提案をしつつ、もくもくと開発していることが多いエンジニアです。

常駐のため、現場が変わるごとに面談があり(法律なんか知らん)、その度にやばそうな雰囲気の出てる案件は基本的に避けるようにしています。
現場に入る前の面談で、これを確認すれば、地雷案件を少し回避できるポイントがなんとなくわかってきたので、メモっておきます。
※あくまで個人的な指標であって、なんの根拠もないです!!

保守案件の場合は、アプリのストア評価を確認

保守案件で、ストアの評価が低いアプリは可能な限り参画を回避します。

理由は、

  • ストアの評価が低いものは、内部の品質が基本的に低い
  • 新たな開発はできずに、既存バグの修正に追われて疲弊する
  • ただのバグ修正ではスキルがつきにくい
  • クソコードを見ると発狂する(コントローラにAPIリクエストが入っているとか無理)
  • ひどい場合、gitすら使ってない
  • その他色々

だからです。
何より、過去に低評価アプリを3つほど、保守・機能追加を担当して、すごく苦労したので

アプリのアーキテクチャーを確認

  • 全てをControllerに実装するアーキテクチャ
  • MVC
  • MVVM
  • VIPER
  • CleanArchitecture
  • など

色々とありますが、開発するアプリのアーキテクチャが決まっている場合があるので、確認します。

保守開発の案件で、既存のアーキテクチャを教えていただけることがあるのですが、
なぜか「CleanArchitecture」を使用してると言われるプロジェクトは、クラス名だけCleanArchitectureで、中身はぐちゃぐちゃの地雷が多いです。

経験上、「CleanArchitecture」と「全てをControllerに実装するアーキテクチャ」は避けたい対象となっています。

常駐先の会社さんにアプリ開発をできるプロパーさんがいるか確認

受託開発の新規作成案件で、アプリを開発できるエンジニアさんがいない会社が受けた場合、要件定義や見積もりでやらかしている可能性がかなり上がります。
Web画面を作る感覚でアプリの見積もりをしてしまった案件の場合は、開発工数がそもそも足りていない場合が多くあるイメージです。

見積もりが多い分には、常駐する側としては問題ないのでが、やらかしている可能性が高い案件の場合が多いので、なるべく避けるのがおすすめです。

開発者を複数人募集している案件は、他のメンバーのスキルを確認

最近の案件は、1アプリを2~3人くらいで新規開発をする案件がそこそこあるイメージです。
ただし、複数人開発と言えど、

  • 新人さん(2年未満)
  • アプリを一人で作ったことのない人

が相方として参画しそうな場合は、申し訳ないですが確実に避けるようにしています。
(他の人の面倒を見るのは避けたい。ただし、面倒を見る費用をもらえる場合は別途相談)

また、開発規模の割に人数が多い案件の場合は、
スキルの低い人間を集めて、クライアントへの見積もりをカサ増ししている案件が多いです。
(できる人が1人で2ヶ月できるのを、4人で半年とか)
結局、できる人間が全て作るハメになるので、避けるようにしています。

SIer系は避ける

会社さんによりますが、古いルールとかに縛られていることがあるので、近づかないほうがいいイメージ。
特にスーツ必須のところは、ちょっと怖い。
※うちは、違うぜ!だ感じの会社さんはごめんなさい。経験上は、どうしても多いのです。

フロアのエンジニアの残業状況を確認

面談の際に常駐先のエンジニアの残業状態を確認します。
残業をしている人が多い場合は、だらだら仕事する癖がついている or 仕事量がおかしい 現場の可能性が高いので、なるべく避けます。

質問は、自分から質問すると残業を避けたがるエンジニアのイメージがつく気がするので、営業から質問してもらえるようにお願いするのがベストです。

スクラム開発の場合に、スクラムの前提を満たしているか確認

最近流行っているスクラム開発を取り入れている案件がそこそこ出てきました。
ただし、スクラムをやる上で、前提条件を満たしていない案件が多いので注意が必要です。

  • 全機能ができる納期がある????
  • スキルがバラバラすぎる
  • クライアントがスクラム開発に乗り気ではない(POさんがいないとか)
  • スクラムを銀の弾丸と思っている人がいる(スクラムだから開発に成功するとか)

(前提条件を満たしていない時点で、スクラムではないと思いますが。。。)

また、これは個人的な都合ですが、以下の点でスクラム開発はちょっとやりにくいところがあります。

  • 作業見積もりをごまかしにくい
  • 最初に一気に開発して、開発期間の最後の方でゆっくりすることがしにくい(開発期間の余ったところでだらだらするのが趣味のため)
  • 全員バラバラの所属で、ガッチリとしたチームプレーはちょっとめんどい

色々、ネガティブなことを書いてますが、うまくはまっているスクラム開発は色々と新しいことができて楽しいのでおすすめです!!

開発環境の確認

  • Mac/PCの簡単なスペック(メモリ8GBじゃ辛い)
  • iPhoneなどの実機の有無

などを念の為確認すると、あとで開発中にイライラするのを防げるかもしれないです。

まとめ

色々書きましたが、結局は現場に参画してみないとわかりません。
iOSアプリを開発すると聞いていて、Androidアプリを開発することはよくあるので。。。
スキルが複数ある場合は、しれっと他の案件にすり替わってることがあるので、回避不可能です。

わざわざ、大変だったり辛い現場に行くのは勿体無いので、
お金をもらえながら、楽しくてスキルのつける現場になるべく行けるように、これからも頑張って面談していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】画面遷移の方法(俯瞰用)

値の受け渡しや求めるUIに合わせた記述の仕方など、単純に見えてバリエーションの多い画面遷移についてまとめます。
performSegueやら、popViewControllerやら、dismissやら、InterfaceBuilderやら、コーディングやら地味にバリエーションが多くてめんどくさくないですか?
今まで経験則でなんとなく使ってきましたが、詰まってはググってを繰り返していたので一度使い方をまとめたいと思います。
備忘録的な記事になりますが、ご容赦願います。

画面遷移で混乱すること

  • コーディングとかInterfaceBuilderとか実装方法がいくつかあって忘れる
  • 遷移の種類がいくつかあって混乱する(showとかmodalとか)
  • 画面間の値の受け渡しでコケる
  • 画面から戻るときにコケる
  • 上記の組み合わせで実装方法が違って泣く

僕は上記のようなことでよく詰まります。
ですので、以下ではこの辺をなんとなく整理できたらなと思います。

画面遷移の実装方法

画面遷移の実装方法は主に以下の三つ。
A. InterfaceBuilder(ボタンと画面をSegueで接続)
B. InterfaceBuilder(Segue Identifier) + コーディング
C. InterfaceBuilder(Storyboard ID) + コーディング

ボタンを押したら遷移するだけなどの簡単な処理はAパターンで良いとして、
多くの場合はボタン押下時になんらかの処理を実行するケースが多いと思います。
それに伴いBパターン、Cパターンもしっかり使えるようになっておく必要があります。

B. InterfaceBuilder(Segue Identifier) + コーディング

遷移元・先のViewControllerをSegueで繋げた後に、SegueのIdentifierを設定。
その際に画面遷移の種類(Show,Present Modalyなど)を指定することができます。
これにより遷移したいタイミングで

performSegue(withIdentifier : "toNextViewController", sender: nil)

などとすることで遷移を実行できます。
ちなみにsenderによってボタンからの遷移実行なのかtapGestureRecognizerなのか、segueの出し元の判定ができます。

C. InterfaceBuilder(Storyboard ID) + コーディング

遷移先のStoryboardにIDを振り、コードでそのViewControllerを呼び出します。
実際のコード例は以下。

// Storyboard、ViewControllerを指定
// 同じStoryboard上であればselfを用いて指定
let storyboard: UIStoryboard = self.storyboard!
let next: UIViewController = storyboard.instantiateViewController(withIdentifier:"nextViewController") as! UIViewController
// 遷移処理
navigationViewController.pushViewController(next, animated: true, completion: nil)

Storyboard IDを利用して遷移先のViewControllerのインスタンスを取得した後に、遷移先の処理を実行します。

画面遷移の種類

画面遷移のバリエーションは5つ?くらいあるけど、実際よく使うのは、
ShowPresent Modaly の二つと思われます。
一旦それ以外の遷移の種類は忘れることとして、それぞれについてまとめます。

Show

遷移元の画面から横にズイっと新しい画面が現れる遷移。
NavigationControllerの管理下で使うことが多いです。
rootViewControllerに対して次々にShowで画面を繋げた場合、
Showで繋げたviewcontrollerはrootViewControllerの子となります。

NavigationController管理下における、
A_ViewController -> B_ViewControllerへの遷移では、
pushViewControllerメソッドを用いて、showの遷移が可能です。
(先ほどCパターンの実装例であげた実装例)

AViewContoller.swift
let next: UIViewController = storyboard.instantiateViewController(withIdentifier:"nextViewController") as! B_ViewController
navigationViewController.pushViewController(next, animated: true, completion: nil)

また、遷移先のB_ViewControllerから遷移元に戻るときは、popViewControllerメソッドを使うことで遷移元に戻ることができます。

BViewContoller.swift
navigationViewController.popViewController(animated: true)

Present Modaly

Viewの上に覆いかぶさるような形で下から新たなViewが現れる遷移。
一時的なユーザーの操作受付やオンボーディングからアプリの本機能への遷移時など、つながりをあえて切りたいときによく使われます。
iOS13以降ではデフォルトの遷移がフルスクリーンではなく、Safariのタブのような重なり方となっており、必要に応じてフルスクリーンの設定が必要になります。

このパターンでも同様に、
A_ViewController -> B_ViewControllerへの遷移を考えたとき、
遷移元からは

A_ViewContoller.swift
let next: UIViewController = storyboard.instantiateViewController(withIdentifier:"nextViewController") as! B_ViewController
self.present(next,animated: true, completion: nil)

にて遷移ができ、遷移先からは

B_ViewContoller.swift
self.dismiss(animated: true, completion: nil)

dismissメソッドにて遷移元に戻ることが可能です。

まとめ

今回画面遷移の方法について、実装方法・代表的な遷移の種類・各メソッドの位置付けをまとめました。
今回書ききれなかった画面間の値渡しや、画面遷移時の処理など、時間のあるときに書きたいと思います。
見ていただいた方、ありがとうございました。

参考

【iOS】画面遷移方法まとめ
【Swift/iOS】遷移元画面への戻り方
【Swift/iOS】Segueを使わない画面遷移

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【react-native】 pod instal 時の glog(0.3.5) でのエラー

最初に

新しい MacBook に react-native の環境を構築しようとしたところ謎のエラーが出て...丸1日ハマりました。
20191126-01.png

発生したエラー内容

Installing glog (0.3.5)
/bin/bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

pod install 時に glog(※) の ios-configure-glog.sh にて Windows でも馴染みの 改行コード CRLF で保存されたスクリプトが実行される ことで解析エラーとなっています。

   ※Google のログ出力用のライブラリ

試したこと

他の MacBook 環境では発生しなかったので完全に原因が不明でした。
この問題を解決させるために、

  • ruby の各バージョンのインストール
  • node.js の各バージョンのインストール
  • cocoapod の各バージョンのインストール
  • XCode 10.1, 10.2, 11.1 を再インストール
    • xcode-select で SDK ツールの切り替え

とやったのですが、全く効果が見られませんでした...(´;ω;`)

最終的にはこちらの記事を参考に、試行することで解決できたので謝辞とともに手順を記載していきます。
素晴らしい調査ありがとうございます。

対応策としては 「CRLF になってしまうなら LF に直せば良いよね」という発想です。

まずは変換ツールを入れよう

# Homebrew で CRLF=>LF に変換するツールをインストールします
brew install dos2unix

これが無いと始まらないです。

ツールを入れたら...

対象プロジェクトで yarn install は予め行っておき node_module が存在する 状態にしておきます。
その後「テキストエディタ」で下記ファイルを開き、

node_modules/react-native/scripts/ios-configure-glog.sh

31 行目の ./configure と記載されてる一つ前の行に

dos2unix -f *

上記コードをコピーし挿入します。編集後は、下記のようになります。
20191126-02.png

その後、ターミナルで iOS ディレクトリに移動し pod install を行うと....
20191126-03.png

無事、成功しました。

ただこの後 XCode でビルドエラーが起きてしまうことがあるので、その場合は node_module 内の glog/config.h を Pods に手動コピーする必要があります。

# プロジェクトの TOP ディレクトリに移動して実行する
cp node_modules/react-native/ReactAndroid/src/main/jni/third-party/glog/config.h ios/Pods/glog/src

※名前が ReactAndroid となっていますが正しいです。

終わりに

問題は解決したのですが、PC によってこの事象が発生したりしなかったりする根本的な原因がわからなかったです。
glog が CRLF で保存されているなら、すべての MacBook で本事象が起きてもおかしくないハズ...

なぜこうなってしまうのか原因がわかる方がいたら教えていただけますと幸いです。

参考記事:
pod install errors on newly detached app on MacOS installing GLog - : /bin/bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【react-native】pod instal 時の glog(0.3.5) でのエラー

最初に

新しい MacBook に react-native の環境を構築しようとしたところ謎のエラーが出て...丸1日ハマりました。
20191126-01.png

発生したエラー内容

Installing glog (0.3.5)
/bin/bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

pod install 時に glog(※) の ios-configure-glog.sh にて Windows でも馴染みの 改行コード CRLF で保存されたスクリプトが実行される ことで解析エラーとなっています。

   ※Google のログ出力用のライブラリ

試したこと

他の MacBook 環境では発生しなかったので完全に原因が不明でした。
この問題を解決させるために、

  • ruby の各バージョンのインストール
  • node.js の各バージョンのインストール
  • cocoapod の各バージョンのインストール
  • XCode 10.1, 10.2, 11.1 を再インストール
    • xcode-select で SDK ツールの切り替え

とやったのですが、全く効果が見られませんでした...(´;ω;`)

最終的にはこちらの記事を参考に、試行することで解決できたので謝辞とともに手順を記載していきます。
素晴らしい調査ありがとうございます。

対応策としては 「CRLF になってしまうなら LF に直せば良いよね」という発想です。

まずは変換ツールを入れよう

# Homebrew で CRLF=>LF に変換するツールをインストールします
brew install dos2unix

これが無いと始まらないです。

ツールを入れたら...

対象プロジェクトで yarn install は予め行っておき node_module が存在する 状態にしておきます。
その後「テキストエディタ」で下記ファイルを開き、

node_modules/react-native/scripts/ios-configure-glog.sh

31 行目の ./configure と記載されてる一つ前の行に

dos2unix -f *

上記コードをコピーし挿入します。編集後は、下記のようになります。
20191126-02.png

その後、ターミナルで iOS ディレクトリに移動し pod install を行うと....
20191126-03.png

無事、成功しました。

ただこの後 XCode でビルドエラーが起きてしまうことがあるので、その場合は node_module 内の glog/config.h を Pods に手動コピーする必要があります。

# プロジェクトの TOP ディレクトリに移動して実行する
cp node_modules/react-native/ReactAndroid/src/main/jni/third-party/glog/config.h ios/Pods/glog/src

※名前が ReactAndroid となっていますが正しいです。

終わりに

問題は解決したのですが、PC によってこの事象が発生したりしなかったりで根本的な原因がわからなかった。
glog が CRLF で保存されているなら、すべての MacBook で本事象が起きてもおかしくないハズ...

なぜこうなってしまうのか原因がわかる方がいましたら教えていただけますと幸いです。

参考記事:
pod install errors on newly detached app on MacOS installing GLog - : /bin/bash: ./configure: /bin/sh^M: bad interpreter: No such file or directory

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift/iOS】CoreLocationで取得した位置情報を住所に変換する

概要

下記の記事で説明した位置情報から自然な住所の表記に変換する方法について説明します。
【Swift/iOS】CoreLocationで緯度・経度を取得して位置情報を表示する

位置情報を取得した場所によって地名として取得される情報の粒度が異なるため、地名をつなげるだけでは自然な住所表記にならない場合があります。
具体例としては、下記の実行結果をご覧ください。

確認バージョン

Xcode 11.2.1
Swift 5.1.2
iOS 13.2.2

要件

  1. 地名が丁目や番地まで取得できる場所では丁目や番地までの住所を出力
  2. 地名が「〜通り」や「〜道路」などの場合には丁目なしの住所を出力
  3. 「〜通り」や「〜道路」は住所に含めない

結論

下記のように実装すると要件を満たす住所が出力されました。

//位置情報
let administrativeArea = placemark.administrativeArea == nil ? "" : placemark.administrativeArea!
let locality = placemark.locality == nil ? "" : placemark.locality!
let subLocality = placemark.subLocality == nil ? "" : placemark.subLocality!
let thoroughfare = placemark.thoroughfare == nil ? "" : placemark.thoroughfare!
let subThoroughfare = placemark.subThoroughfare == nil ? "" : placemark.subThoroughfare!
let placeName = !thoroughfare.contains( subLocality ) ? subLocality : thoroughfare

//住所
let address = administrativeArea + locality + placeName + subThoroughfare

説明

プロパティ名 概要 説明
administrativeArea 都道府県 そのまま(nilにはならないはず)
subAdministrativeArea 町村の場合、localityに〜郡〜町/村と出力されるのでこちらは使用しません
locality 市区町村 そのまま(nilにはならないはず)
subLocality 丁番なしの地名 thoroughfareにsubLocalityが含まれない場合はsubLocality
thoroughfare 地名 上記以外はthoroughfare
subThoroughfare 番地 nilの場合は空白

実行結果

出力される住所は下記の画面の最終行に表示されています。

永田町2丁目 永田町 日比谷公園 奥多摩町
スクリーンショット 2019-11-26 23.49.06.png スクリーンショット 2019-11-26 23.58.09.png スクリーンショット 2019-11-26 23.53.09.png スクリーンショット 2019-11-26 23.51.56.png

実装

  1. 情報表示用のUILabelを追加
  2. 位置情報を利用許可状態を判定
  3. 位置情報の更新開始
  4. CLLocationデータを逆ジオコーディングして位置情報を取得
  5. 位置情報を住所に変換
  6. 位置情報が更新されるごとにUILabelに設定
import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {
    let locationManager = CLLocationManager()
    let geocoder = CLGeocoder()
    let text = [ "緯度", "経度", "国名", "郵便番号", "都道府県", "郡", "市区町村", "丁番なしの地名", "地名", "番地" ]
    var item: [ UILabel ] = []
    var location: [ UILabel ] = []
    var address: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        //サイズ
        let width = self.view.frame.width / 2
        let height = self.view.frame.height / CGFloat( self.text.count + 2 )

        //ラベル
        for ( i, text ) in self.text.enumerated() {
            //項目
            self.item.append( UILabel() )
            self.item.last!.frame.size = CGSize( width: width, height: height )
            self.item.last!.frame.origin = CGPoint( x: 0, y: height * CGFloat( i + 1 ) )
            self.item.last!.textAlignment = .center
            self.item.last!.text = text
            self.view.addSubview( self.item.last! )

            //データ
            self.location.append( UILabel() )
            self.location.last!.frame.size = CGSize( width: width, height: height )
            self.location.last!.frame.origin = CGPoint( x: width, y: height * CGFloat( i + 1 ) )
            self.location.last!.textAlignment = .center
            self.view.addSubview( self.location.last! )
        }

        //住所
        self.address = UILabel()
        self.address.frame.size = CGSize( width: self.view.frame.width, height: height )
        self.address.frame.origin = CGPoint( x: 0, y: height * CGFloat( self.text.count + 1 ) )
        self.address.textAlignment = .center
        self.view.addSubview( self.address )

        //ロケーションマネージャ
        self.locationManager.requestWhenInUseAuthorization()
        let status = CLLocationManager.authorizationStatus()
        if status == .authorizedWhenInUse {
            self.locationManager.delegate = self
            self.locationManager.distanceFilter = 10
            self.locationManager.startUpdatingLocation()
        }
    }

    func locationManager( _ manager: CLLocationManager, didUpdateLocations locations: [ CLLocation ] ) {
        //表示更新
        if let location = locations.first {
            //緯度・経度
            self.location[0].text = location.coordinate.latitude.description
            self.location[1].text = location.coordinate.longitude.description

            //逆ジオコーディング
            self.geocoder.reverseGeocodeLocation( location, completionHandler: { ( placemarks, error ) in
                if let placemark = placemarks?.first {
                    //位置情報
                    self.location[2].text = placemark.country
                    self.location[3].text = placemark.postalCode
                    self.location[4].text = placemark.administrativeArea
                    self.location[5].text = placemark.subAdministrativeArea
                    self.location[6].text = placemark.locality
                    self.location[7].text = placemark.subLocality
                    self.location[8].text = placemark.thoroughfare
                    self.location[9].text = placemark.subThoroughfare

                    //住所
                    let administrativeArea = placemark.administrativeArea == nil ? "" : placemark.administrativeArea!
                    let locality = placemark.locality == nil ? "" : placemark.locality!
                    let subLocality = placemark.subLocality == nil ? "" : placemark.subLocality!
                    let thoroughfare = placemark.thoroughfare == nil ? "" : placemark.thoroughfare!
                    let subThoroughfare = placemark.subThoroughfare == nil ? "" : placemark.subThoroughfare!
                    let placeName = !thoroughfare.contains( subLocality ) ? subLocality : thoroughfare
                    self.address.text = administrativeArea + locality + placeName + subThoroughfare
                }
            } )
        }
    }
}

Githubのソースコードはこちら

緯度・経度の確認方法について

住所から緯度・経度を確認するのに下記のサイトを使用しました。
いろいろな住所で変換結果が正しいことを確認するのに重宝しました。
https://www.geocoding.jp

このサイトで検索した緯度・経度を下記のように入力すると、その場所での位置情報を確認することができます。

//緯度・経度
let location = CLLocation( latitude: 35.675775, longitude: 139.743488 )

//逆ジオコーディング
self.geocoder.reverseGeocodeLocation( location, completionHandler: {
   //以下、略

参考

【CoreLocation】位置情報を取得する
[iOS] MapKitを使って”ジオコーディング・逆ジオコーディング”をやってみる

開発アプリ

私が開発したアプリを紹介します。
この記事とは直接関係ないのですが、興味があればダウンロードしてもらえると嬉しいです。
NomiReco - お酒好きなあなたをサポート

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SwiftUIのTabViewの問題に自作TabView(SwiftUI製)で対処する

SwiftUIのTabViewの問題に自作TabView(SwiftUI製)で対処する

 

SwiftUIのTabViewには、Tabを切り替えると切り替えた先のタブを再生成するためスクロールした位置や状態を保持しておくことができませんでした。

それに対処するために、今回自作TabViewを作成しましたので、その tipsを共有します。

作成したTabViewを見たい方はこちらから!
https://github.com/tsuzukihashi/SwiftUI_CustomTabBar

また、UIKitのUITabBarControllerを Representaぶる方法もあります。そっちの方がiOS的には優しいかもしてません...

こっちのメリットは、タブ切り替えのアニメーションがいじりやすいのと、オールSwiftUIのモチベぐらいでしょうか...

間違いやアドバイスがあればじゃんじゃんコメントください!お願い致します?‍♂️

Twitter やっています!
https://twitter.com/tsuzuki817

色々アプリをリリースしているので一度見てみてください?‍♂️
https://apps.apple.com/jp/developer/ryo-tsudukihashi/id1320583602?l

現状の問題を把握

先ほど説明しましたが、改めてGIFアニメーション載せておきます。
2tdvx-fuo22.gif

自作TabViewへの道

大まかな流れは以下のようになっています。

  • ステップ1 ルートのViewで現在選択しているcurrentPageを保持する
  • ステップ2 ルートのViewでタブで遷移したいViewをZStackで並べる
  • ステップ3 ステップ2で配置したViewのopacityをcurrentPageによって変える
  • ステップ4 タブもどきに設置したボタンでcurrentPageを切り替える

説明しやすいように、シンプルなアプリを作成します。

表示させたいView達

変化が分かりやすいように縦に多くスクロールできるViewを作成しています。

Page2では天下のイラストや様の画像を少しばかりお借りしております。

import SwiftUI
struct Page1: View {
    var body: some View {
        NavigationView {
            VStack {
                List(0..<30) { i in
                    Text("\(i)列目")
                }
            }.navigationBarTitle("1ページ目")
        }
    }
}

struct Page2: View {
    var body: some View {
        NavigationView {
            ScrollView(.vertical, showsIndicators: false) {
                ForEach(1..<8) { i in
                    Image("irasutoya\(i)")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                }
            }.navigationBarTitle("2ページ目")
        }
    }
}

struct Page3: View {
    var body: some View {
        NavigationView {
            VStack {
                List(0..<30) { i in
                    Text("\(i)列目")
                }
            }.navigationBarTitle("3ページ目")
        }
    }
}

ルートのView

このViewで@State で currentPageを保持しておきます。
そのcurrentPageの値を見てViewのopacityを変更して、表示・非表示を切り替えています。

また、ここでoffsetをいじっているのですが、これはアニメーションのために利用しています。

そのためアニメーションを利用しない方は、なくてもおkです!
(.rotation3DEffectとか使ったらリッチになって面白そうだったのですが、navigationbar が少しおかしくなりました;;)

import SwiftUI

struct ContentView: View {
    @State  var currentPage = 1

    var body: some View {
        ZStack {
            Page1()
                .opacity(currentPage == 1 ? 1 : 0)
                .offset(x : currentPage == 1 ? 0 : 100)
                .animation(Animation.spring())

            Page2()
                .opacity(currentPage == 2 ? 1 : 0)
                .offset(x : currentPage == 2 ? 0 : 100)
                .animation(Animation.spring())

            Page3()
                .opacity(currentPage == 3 ? 1 : 0)
                .offset(x : currentPage == 3 ? 0 : 100)
                .animation(Animation.spring())

            MyTabView(currentPage: $currentPage)
        }
    }
}

肝心の自作TabView

@BindingでcurrentPageをルートViewから受け取り、設置するボタンでその値を変更します。

VStack, Spacer() , ZStack, Rectangleを駆使して擬似タブを作成します。

.edgesIgnoringSafeArea(.bottom)を使って、セーフエリアまで覆うのを忘れないようにしておけば、後は結構自由です。

struct MyTabView: View {
    @Binding var currentPage: Int
    var width = UIScreen.main.bounds.width
    var body: some View {
        VStack {
            Spacer()
            ZStack {
                Rectangle()
                    .foregroundColor(Color.gray)
                    .frame(width: width, height: 88)

                HStack(spacing: 88) {
                    Button(action: {
                        self.currentPage = 1
                    }) {
                        VStack {
                            Image(systemName: "flame")
                                .foregroundColor(Color.red)
                                .font(.system(size: 32, weight: .bold, design: .rounded))

                        }
                    }.padding(.bottom, 24)

                    Button(action: {
                        self.currentPage = 2
                    }) {
                        VStack {
                            Image(systemName: "bolt")
                                .foregroundColor(Color.yellow)
                                .font(.system(size: 32, weight: .bold, design: .rounded))

                        }
                    }.padding(.bottom, 24)

                    Button(action: {
                        self.currentPage = 3
                    }) {
                        VStack {
                            Image(systemName: "leaf.arrow.circlepath")
                                .foregroundColor(Color.green)
                                .font(.system(size: 32, weight: .bold, design: .rounded))

                        }
                    }.padding(.bottom, 24)

                }
            }
        }.edgesIgnoringSafeArea(.bottom)
    }
}

できたもの

6t67u-qqz8z.gif

タブを切り替えてもViewは作り直されず、遷移前の状態を保持することができました!

最終的な着地点

以上で実装は終わりです!

SwiftUIは色々不便なことも多いですが、楽しいですね!

そのうちTabViewの問題もApple様が直してくれそうですが、一時的な場しのぎとしてどうでしょうか

最後にもう一度作成したリポジトリです!
https://github.com/tsuzukihashi/SwiftUI_CustomTabBar

閲覧ありがとうございましたmm

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む