20201104のSwiftに関する記事は12件です。

FireStoreでデータを検索して更新する[ Swift ]

都道府県リストから、"Osaka"という名前の都道府県を検索して"行ったことがある"というフラグをFalseからTrueにします。

let doc = Firestore.firestore().collection("prefectures") // prefectureリスト
          .whereField("name", isEqualTo: "osaka").getDocuments(completion: {  // 名前が大阪と一致するドキュメントをとってくる
 (querySnapshot, error) in
                    if let err = error {
                        print("Error getting documents: \(err)")  // エラーハンドリング
                    } else {
                    let id = querySnapshot.documents.first?.documentID  // 結果のドキュメントIDをとる
                    let document = Firestore.firestore().collection("prefectures").document(id!) // IDと一致する書き換えできるドキュメントをとる
                    doc.updateData([ // アップデート
                        "haveBeenTo": true // 行ったことあるフラグをTrueにする
                    ]) { err in
                        if let err = err { // エラーハンドリング
                            print("Error updating document: \(err)")
                        } else { // 書き換え成功ハンドリング
                            print("Update successfully!")
                        }
                    }
                }
            })

*これは、Name:Osakaというドキュメントがひとつしかないことが保証されている場合だけできます。もしOsakaが二つあると、望んでいない方が更新されることがあります。一意にドキュメントを取得するには、IDを使用します。

?

?


お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

Twitter
Medium

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

SwiftUIのListでRealmのデータを削除するとクラッシュする時の直し方

Index is out of bondsでクラッシュ!

SwiftUIのListの.onDeleteでperformに下記のメソッドを渡し、

func deleteRow(offsets: IndexSet) {
      guard  let index = offsets.first else {
           return
      }
      let deleteItem = hoges[index]
      try! realm.write {
        realm.delete(deleteItem)
      }
      self.hoges = realm.objects(Hoge.self)
}

試しに、このように記述していたら、 "Index ~ is out of bounds (must be less than ~)." とよく見るエラーでクラッシュしてしまいました。

クラッシュしない書き方

https://stackoverflow.com/questions/61165998/how-to-delete-data-from-swiftui-list-and-realm

こちらを参考にindexをforEachで回すようにしたらクラッシュしなくなります!

func deleteRow(offsets: IndexSet) {
      offsets.forEach({ index in
       try! realm.write {
         realm.delete(self.hoges[index])
        }
      })
      self.hoges = realm.objects(Hoge.self)
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift・脱初心者】通信周りの関数は別ファイルに書こう

勉強を初めて間もない頃は、全ての処理をViewControllerに書いているかと思います。

そのような書き方で出来上がったViewControllerをFatViewController

太ったViewControllerといいます。

FatViewControllerになるほど可読性が落ち、保守性が落ちていきます。

そうならないためにアーキテクチャと呼ばれる設計思想があります。

Viewに関する処理はここに、ビジネスロジックはここに、等

コード品質を下げないためのルールです。

初めからこれにのっとるのは難しいので、まずはAPI通信に関することを切り分けていきましょう。

通信周りの処理を分ける

通信周りの処理はまず、
・APIを投げる関数(クロージャでレスポンスを返す)
 リクエストを投げ、レスポンスをクロージャで返却します。
・レスポンスをマッピングするための構造体(Codable)
 Codableに準拠して、返ってくるJsonデータに合わせてコーディングする部分
・APIのレスポンスを処理する
 実際にデータを使用する処理
の3つに分けてあげます。

まずこれができるようになれば、
脱初心者への道を1歩進むことができます。

おわりに

最終的にMVVMと呼ばれるアーキテクチャに沿ったコーディングができると
完全に脱初心者ですが、初めからそれは難しいので
せめて通信周りだけでも分けて書くように意識してみてください。

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

【Swift・脱初級】Enumを使って保守性のあるコーディングをする

保守性のあるコードにするために、しばしばenumを用いることがあります。
簡単な例で見てみます。

var direction = ""
if right = "right" {
    direction = "right"
} else {
    direction = "left"
}

一見、問題なさそうに見えます。
その通りで問題ありません。
が、保守性という観点からみると改善点が見えてきます。

//ファイルA.swift
enum Direction {
  case right
  case left
}

//ファイルB.swift
var direction:Direction?
if right = "right" {
    direction = .right
} else {
    direction = .left
}

enumを使うことで、このように決まったパターンに絞って
処理を書くことができます。
このように制約をつけることは、プログラミングでいう保守性においてとても重要な考え方です。
自由に記述できることはすなわち、決まりのないバラバラなコードになる可能性が高いということです。
あえて制約をつけて不自由にすることで、決まりのある保守性にそったコードを書くことができます。

おわりに

いかがでしたでしょうか
一見面倒に見えますが、慣れると簡単です。
保守性のあるコードを書くことは脱初心者になるので、ぜひ挑戦してみてください。

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

【Swift・初学者向け】型推論でスマートに書く

型推論でスマートにかけるパターン

let str:String = "Hello"
let str = "Hello"   
//右辺の"Hello"がString型なので、暗黙的にstrはString型になる
let color:UIColor = UIColor.red
let color:UIColor = .red  
//左辺で明示的にUIColorを宣言しているので、右辺のUIColorを省略できる
UIView.animate(withDuration: 1, delay 1, 
options: UIView.AnimationOptions.curveEaseIn, 
animations: { }, completion: nil)

UIView.animate(withDuration: 1, delay 1,
options: .curveEaseIn,
animations: { }, completion: nil)
//引数の型がUIViewのAnimationOptionsなので省略できる

型推論で書くと処理コストが増大するパターン

(参考)
https://t.co/j5Yq9fIrQO?amp=1

let add = (num1 ?? 0 as Int) + (num2 ?? 0 as Int) + (num3 ?? 0 as Int)
//型を明示した方が処理が早くなる
let add1 = num1 ?? 0 as Int
let add2 = num2 ?? 0 as Int
let add3 = num3 ?? 0 as Int
let sum = add1 + add2 + add3
//先にunwrapしたり、複雑な式の場合は分解してから計算した方が優しい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】Storyboardのメリット・デメリット

駆け出しの方の多くがまず、storyboardでUI作成をするかと思います。

ぱっと見、直感的にでき、わかりやすいと感じるのではないでしょうか。

その通りで、Storyboardのメリットは直感的にわかりやすいことにあります。

ですが開発をしていくうちにそんなStoryboardにも大きなデメリットがあることに

気付きます。

デメリット

重い

とにかくstoryboardは重いです。
1つのstoryboardに全ての画面をまとめていくと、開くだけで動かなくなることがあります。そのため、storyboard referenceを使ったりライブラリを使ってstoryboardを分割したりするところもあります。

管理が難しい

コーディングベースではないので、いざコンフリクトするともう終わりです。
どちらかの実装が消えることになるでしょう。
また、デバッグ時にエラーを吐かないので、デバッグが難しくなります。
さらにはGithubやsourcetree上でレビューすることができないので
なかなか管理コストが高いと言えます。

Appleが推奨していない?

SwiftUIでは、コーディングベースのUIの描画になっています。
これはstoryboardの教訓からでしょうか?
Canvas機能でビルドすることなくプレビューの確認と操作ができるSwiftUIは画期的で、
これはstoryboardからの脱却も意味していると言えます。

終わりに

いかがでしたでしょうか。
もちろん、時と場合によってはstoryboardの方がずっと便利かもしれませんが、
基本的にはコーディングによるUIの描画に慣れておくべきかと思います。

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

【Swift】FlowLayoutはインスタンスでなくDelegateを使うべきな理由

実務でCollectionViewを使った実装があり、
その時にFlowLayoutインスタンスを使って
端末毎に描画の差異が出てハードコードになってしまったので、
この記事を書きました。

なるべくDelegateFlowLayoutを使うべき理由

これにはライフサイクルが関係しています。
https://qiita.com/Sossiii/items/4ffcbc07d9ccecab6420

インスタンスを使う場合、ライフサイクルに関係なく
実装者のタイミングで描画処理を実行することができます。
これは、適切ではないタイミングで実行させると、
描画がうまくいかないことを意味します。

これが原因で、iPhoneのMax系とSE1で
レイアウト崩れ(ロジック通りに反映されない)が起き、
ハードコードによって補正することになりました。

ライフサイクルが原因であり、DelegateFlowLayoutで解決できると
わかったことでハードコードが解消されました。

結論

FlowLayoutはインスタンスではなく
DelegateFlowLayoutを使うのが無難

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

【Swift】ライフサイクルを知らないと描画の更新につまずく話:駆け出し向け

描画の更新処理において、
「なぜか反映されない」
という場面に何度か遭遇してきました。

そんな時には大体、「ライフサイクル」が関係しています。
UIViewControllerやUIViewなど、クラスには処理の流れと言うものが存在します。

ファイル作成時に必ず見る、super.viewDidLoad()がまさにその一部です。

以下、UIViewControllerのライフサイクル
https://qiita.com/motokiee/items/0ca628b4cc74c8c5599d

ライフサイクルを建築に例えてみましょう。
家を作る時、まず土台を作り、その上で骨組みを作ります。
そして壁や屋根、その後に家具などを運び入れます。
この時、土台を作らずして骨組みを立てていくことはできません。
また壁を塗装するには壁が必要になります。

これと似たような話がライフサイクルです。
適切なタイミングで処理を行わなければ、反映されません。

それが「描画が反映されない」と言う現象になります。
そう言った事例に陥ったらまず、継承元のクラスとライフサイクルを調べ、
適切なタイミングで描画更新処理を入れてみましょう。

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

【Swift】未経験から実務までのスキルマップ(ロードマップ)

多くの初学者が無駄なインプットをしすぎている

自分もそうだったのですが、
「どこまで勉強すれば実務に入れるのか」
「何を勉強したら良いのか」
がよくわからず、色々な言語(2桁)を浅く触り、
かなり時間を無駄にしたので、他の未経験の方に
そういったことがないようにここにロードマップを残しておきたいと思います。

プログラミングでは全てを網羅しようとするとキリがないので、
あくまで自分が最低限実務で使っている、多用していることに絞っています。

また、スキルは証明しなければならないので、
深ぼったアプリを作る必要があります。

スキルマップ

基礎構文
新しいことを始めるにはまず、最低限の言葉・文法を知らなければなりません
以下がチェックリストになります。

レベル1:実務は厳しい

・演算(+, -, *, /, %)
・インスタンスとは
・プロパティとは
・メソッドとは
・比較演算子(==, !=)
・変数 var
・定数 let
・エスケープ処理「\()」
・if文
・switch文
・for文
・構造体:struct
・関数 func
・型キャスト

レベル2:数打てばどこか入れるかも

・型推論
・オプショナルがわかる
・if let
・オプショナルチェーン
・画像が使える
・storyboard/コーディングによる描画
 View、TableView、CollectionView、Switch、SegmentedControl
 TableViewとCollectionViewでのカスタムセルによる実装、
 その他もろもろのパーツ
・画面遷移(segue, navigationController,等)
・参照渡し, 値渡し
・アラート UIAlertController,UIAlertAction
・SVProgressHUDを適切なタイミングで使える
・NavigationControllerが使える

レベル3:数打てばどこか入れるかも

・UIView.animateでアニメーションが実装できる
 -> ライフサイクルを意識できると良い
   これができるとUIに磨きがかかるので選考でウケがいい
・セルの再利用がわかり、適切に動作させることができる
 -> 再利用を理解せず(特に初期化)、副作用が起きがち
・selfをつける時、要らない時がわかる

レベル4:入れる確率上昇中

・非同期処理(WebAPIを利用)->DispatchQueueやクロージャを使う
 (クロージャはここで使えれば良さそう)
・ライブラリ(Cocoapodsで外部ファイルをインストールして使う)
 Charts、FSCalendar、SwiftyJSON、とかで良さそう
・Delegateが実用できる
・NotificationCenterが使える
・Githubが使える
・SourceTreeが使える

Delegateは以下の記事が一番わかりやすい
https://qiita.com/Sossiii/items/6c8916f96176991f19aa

レベル5:独学はもう効率悪いから今すぐ実務に入ろう

・Firestore、RealmSwiftを使える
 サーバー上に保存した情報をローカルDBに入れることで、
 何回もFirestoreからデータを引っ張らなくても良い(通信が減る)
 RealmSwiftはメモリ上に保存するのでタスクキルでデータは消え、肥大しない
・チャットが実装できる
 ライブラリ-> MessageKit
・ある程度のUIが設計できる
  Pinterestでググれ

Pinterest(https://tinyurl.com/yyjaansd)

レベル6:即戦力

・RxSwift,Alamofire、SwiftyJSON、Moya, RxCocoa, RxDataSources
 等のライブラリを使用して、MVVMアーキテクチャに基づいたコーディングができる
・既存コードを把握し、それを壊さないコーディングができる(保守)

レベルX:一番重要かも

・ぐぐり力
・ある程度のエラーを自己解決できる
・難題に見切りをつけ、「何がどうわからず、どう調べたが、どうわからなかったので
 こういうことを知りたい」と言った形で質問ができる
・積極的に自習ができる
・プログラミングが好き

最後はポートフォリオを作成

あなたが決めたレベルまでなんとなくできるようになったら、
あとは拘りのアプリを作り上げ、面接に進む時です。

ポートフォリオは拘れ

たまに、「ポートフォリオは要らない」という方がいますが、
自分は「必要」の一択です
スキルレベルのわからない未経験を採用するのに一番わかりやすい
指標が「ポートフォリオ」なので、
必ずと言って良いほど必要です。

ただ、教育リソースがしっかりしていて、未経験の育成に力を入れている
会社であれば手ぶらな状態でも入れるところがあったりします。

その為、広く浅いポートフォリオではなく、
とにかく狭く深くを意識したアプリを作るのをお勧めします。

コンテンツの設計(UX)からデザイン(UI)まで考えられ、
レベル4,5あたりまでの技術を盛り込めば
あとは応募するのみです

コーディング選考に備えるなら

Paiza一択(https://paiza.jp/challenges)

スキル以外に重要なこととは

スキルだけあれば良いのか、と聞かれると実はNoで、
具体的には人としての軸が必要になってきます。
「なぜエンジニアになりたいのか」
「なぜ勉強しているのか」
「あなたはどんな人間なのか」
「実務についたとして続けられるのか」
「何が好きなのか」
このあたりの問いに明確な答えが出てくるようになると、
面接でも特に問題ないかと思います。

企業ニーズに寄せていけ!

私はこういう人間です!受け入れてください!
「は?企業は親じゃねえよ」
会社は成果をあげる場所であって、
あなたを育成するための場所ではありません。
あくまでの成果のためにあなたを育成するのであって、売り上げのために動きます。

選考を通る確率を上げたいのなら、企業ニーズを把握し
それに合わせることはとても大切です
・どんなスキルを歓迎しているのか
・どんなビジョンを持っている会社なのか
・どういう人材を欲しているのか
を把握し、ポートフォリオや面接に盛り込めると尚良しです。

おわりに

個人的にはレベル4,5あたりで応募していきたいところです。
参考になれば幸いです。
また、何ヶ月も勉強しているのに全然できない!
という方に朗報なのですが、1年でスタートラインに立てれば早いものです。
挫折は成長のきっかけであって、それを乗り越えるたびに1歩ずつ進み、
何もしない人との差がそれだけ開いていきます。

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

Swift(iOS)からKotlin(Android)を触る人用の比較メモ1

Siwftでやってきた方がKotlinを触る際の備忘録
概念の違いで特につまづきそうなところをピックアップ

基本的に使うファイル

res配下のdrawable, layout, values
java配下のkotlin(testじゃないやつ)

drawable:iosでいうassetsだがcssのような設定も保存できる
layout:iOSでいうstoryboard
values:iosでいうプロパティをstructなどにまとめて保存するようなところ
     カラーコードやアプリ内テキスト等見ればわかる
kotlin:Activity-iosでいうviewControllerファイルが入ってる

レイアウト

XcodeでいうStoryBoard
AndroidStudioでいうactivity.xml

ConstraintLayoutやLinerLayout, TableLayoutを親として(レイアウトの土台)
その中にパーツを埋めてレイアウトを作っていく。
*以下はそれらLayoutを考慮していない

真ん中に配置したい時

iOS

obj.frame.size.width / 2
obj.center.x(y)
//ストーリーボードならcenterVerticalやHorizontal

Android

app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"

parentは親要素。
指定要素の右側を親要素の右側に、左側を左側に制約を合わせる。
ここを"@id/パーツのid"とすると指定要素に対して設定できる。
左右に均等な制約をつけた為、パーツの左右の力関係は等しく、真ん中に配置される。

app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="10dp"

のように三行目を追加すると、力関係は崩れ、右にmargin10dpが入るので
左に10dpずれる。

ライブラリ管理

iOS

podfile(cocoapods)

Android

Gradle
インストール(iosでいうpod install)は
実行メニューの象さんマーク(Sync Project with Cradle Files)をクリック

画面遷移

iOS

performsegue, navigationController,等

Android

画面移動
Intentインスタンスを使いstartActivityで遷移する
戻る
finish()
startActivityは新たにactivityインスタンスを生成してしまうので、
画面を閉じる(戻る)は特別な理由がない限りfinish()で行う

(もちろん他にもあるが現時点で必要最低限しか実装していないので
これだけ紹介している)

iOSにあってAndroidにないもの

segment control

androidにはこれがないのでRadioButtonのオーバーライドか
ボタンで代用する必要がある

import

iOSではUIパーツをimportすることなく使えるので、
無意識にインスタンスを生成しているが、
Androidでは1つ1つインストールしてあげる。

例えばButtonなら、補完がでたらエンターを押せば自動的にimportを入力してくれる
そうでなければoption+Enterでimportしてくれる

java->Kotlin自動変換

リプレイスに慣れている人ならjavaの記事でもKotlinでかけると思うが
そうでない人は重宝するかも。
javaのコードをエディターに貼り付けると、Kotlinに変換するか問われる
Kotlinの記事が少ないので便利

Kotlinはnullが嫌い

Swiftでは"?"で宣言するが、
Kotlinではそれの他にlateinitをつけたりする

when

iOSでいうSwitch
iOSにはwhenがないのでなんだこりゃ!となるかもしれないのでメモ
when(int) {
1 -> println("int is 1")
2 -> println("int is 2")
}
のようにSwitch文のように使える

おわりに

いかがでしたでしょうか?
Swiftにある程度慣れているのなら、レイアウト部分を理解できれば
ある程度スムーズに行けるのではと思います。
参考になれば幸いです。
間違いがあれば指摘していただければすぐに修正します。

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

[Swift5]スプラッシュ画面の作成方法

スプラッシュ画面とは

アプリケーションを起動した時に表示される画面をスプラッシュ(Splash)画面、またはローンチスクリーン(Launch Screen)と呼びます。アプリケーションにおいては、ユーザーが操作することのできない数少ない画面です。

例を挙げるとtwitterやLineのアイコンが中央に表示されるアノ画面ですね。

デフォルトではアプリケーションを立ち上げた時に真っ白な画面が表示されるようになっております。

作成方法

スプラッシュ画面はXcodeのLaunchScreen.storyboardから作成できます。
image.png

このようにviewに色をつけてみましょう。そうすると。

image.png

アプリケーションを立ち上げたときのviewの色が変わりました。基本的な作成方法は以上です。
文字を入力したい場合などはlabelを貼り付けて編集すればOKです。

注意点

ひとつ注意点ですが、LaunchScreen.storyboardとControllerは紐付けられないようで、紐付けてビルドするとエラーが発生します。

なので、storyboardを使わずにコードでスプラッシュ画面を作成したい方、また動的なスプラッシュ画面を作成したい方は、新規ファイルを作成しSplash.storyboard(例)を作成し、作成したstoryboardとControllerの紐付けをおこない、project/general/App Icon and Launch Images/Launch Screen Fileで作成したstoryboard名を選択してあげればControllerと紐付きます。

最後に

私も今回初めてスプラッシュ画面を触ったので至らない点がありましたらコメントにてお声がけいただければと思います。最後まで読んでいただきありがとうございます!

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

【Swift】入門書では教えてもらえなかった変数の形

1.入門書で教わる変数の形

var Ippanteki = 0

もしくは、

var Ippanteki:Int = 0

2.入門書では教えてもらえなかった変数の形

技術書などを見ていると出てくる変数の形

var notIppanteki:Int {
     return 1
}

正体はComputed Property

で記載した変数の形は値を直接格納する
Stored Property (格納型プロパティ)
と呼ばれています。

それに対して、で記載した変数は、
Computed Property(計算形プロパティ)
と呼ばれるものです。

Computedプロパティは、他のプロパティの値を元に処理を行い、その結果を返す変数で、

読取専用のgetter、書き込みの行えるsetterというものがあります。

今回記載した変数は読取専用のgetterで、
読取専用の場合はgetを省略出来ます。

宣言時には、データ型の記載が必須

var notIppanteki:Int {
return 1
}

このようにデータ型の記載が必要です。
記載しない場合は、

Computed property must have an explicit type
というエラーが出ます。

Computed Propaty(計算型プロパティ)は、詳しい型を必ず持っている必要があります。

つまり、計算型プロパティ宣言時には、データ型の記載が必要ということですね!

まとめ

保存したuserDefaultsの値に応じて変数の値を変更したくて調べました。
おかげでスッキリしました。

var computedPropaty:Int {
if UserDefaults.standard.bool(forKey: "ippanteki") {
    return 0
} else {
    return 1
}

参考

Swift : 変数の後に{ }・・これはComuputedプロパティ(get/set)というものです。
Swift の Read-Only Computed Properties

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