日記アプリを作る。 カレンダーの日付をタップして、その日の日付に対するメモを残す。メモはRealmに保存する。
カレンダー作成
https://qiita.com/ryoegu/items/1e5d1b8cadbf0061f6a7 この記事を大いに参考にしました。
cocoaPod インストール
cocoa podをインストールしていない人は、インストールしましょう。
$ sudo gem install cocoapods $ pod setup
セットアップ完了。 完了したら、作ったプロジェクトのディレクトリでPodfileを作成します。
pod init
自分はDiaryという名前のプロジェクトで作ったので、Diary以下でファイルがあるか確認。Podfileがあればok。
Diary Diary.xcworkspace DiaryUITests Podfile
作ったPodfileの中にJBDatePickerを入れます。
1 # Uncomment the next line to define a global platform for your project 2 # platform :ios, '9.0' 3 4 target 'Diary' do 5 # Comment the next line if you're not using Swift and don't want to use dy namic frameworks 6 use_frameworks! 7 8 # Pods for Diary 9 pod 'JBDatePicker' //↑を追加。 10 target 'DiaryTests' do 11 inherit! :search_paths 12 # Pods for testing 13 end 14 15 target 'DiaryUITests' do 16 inherit! :search_paths 17 # Pods for testing 18 end 19 20 end ~
その後、Diaryディレクトリで以下コマンドを実行。
pod install
これで新たなファイルができるので、作ったファイルをxcodeで開く。
このファイルを開いて、buildしてsuccessするか試してみましょう。
カレンダー作成は以下の記事と同じ。 https://qiita.com/ShinokiRyosei/items/3090290cb72434852460
import UIKit import JBDatePicker class ViewController: UIViewController, JBDatePickerViewDelegate { @IBOutlet var datePicker: JBDatePickerView! lazy var dateFormatter: DateFormatter = { var formatter = DateFormatter() formatter.timeStyle = .none formatter.dateStyle = .medium return formatter }() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. datePicker.delegate = self } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() datePicker.updateLayout() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func didSelectDay(_ dayView: JBDatePickerDayView) { print("date selected: \(dateFormatter.string(from: dayView.date!))") } }
日付タップ後に画面遷移→日記を書く
現在このような表示ですが、表示ができただけでタップしても何も起きません。タップしたら、日記を書くページに画面遷移してみます。
別のview controllerを作る
画面遷移するために、view controllerをもう一個おきます。
作成したら、新しく作ったviewControllerのclassに新しいファイルを割り当てます。
画面遷移するために、別のストーリーボードにcontrolを押しながらくっつけておきましょう。
画面遷移のコードを書く
日付をタップしたら次の画面にいきたいです。タップしたら呼ばれるメソッドがdidSelectDayなので、その中に画面遷移のためのメソッドを書きます。
func didSelectDay(_ dayView: JBDatePickerDayView) { date = "\(dateFormatter.string(from: dayView.date!))" print("date selected: \(dateFormatter.string(from: dayView.date!))") self.performSegue(withIdentifier: "next", sender: nil) //画面遷移のためのメソッド }
withIdentifierの値が"next"になっている部分は、storyboardで設定します。
これで画面遷移はできる。
遷移した先では、送信ボタンをクリックしたら前の画面に戻るようにします。送信ボタンをactionで紐づけて元の画面に戻るコードを書く。
@IBAction func save(_ sender: Any) { self.dismiss(animated: true, completion: nil) }
これで送信ボタンを押したら元の画面に戻ります。
画面遷移時に値を渡す
今回の場合、カレンダーの日付をクリックしたらその日付を一緒に送りたいです。
//viewController func didSelectDay(_ dayView: JBDatePickerDayView) { print("date selected: \(dateFormatter.string(from: dayView.date!))") self.performSegue(withIdentifier: "next", sender: nil) }
dateFormatter.string(from: dayView.date!で取れているので、これを画面遷移先に渡します。
遷移先に渡す際には、以下のメソッドを使います。 self.performSegue(withIdentifier: "next", sender: nil)が呼ばれたら以下のメソッドも呼ばれ、値を次の画面に渡すことができる。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "next" { let secondViewController = segue.destination as! WriteViewController secondViewController.parameters = date } }
ただ、問題はdayViewという値がdidSelectDayメソッドの中でしか使えない点です。prepareメソッドでも使いたいので、グローバル変数にして使います。
var date = "" //上の方に定義
func didSelectDay(_ dayView: JBDatePickerDayView) { date = "\(dateFormatter.string(from: dayView.date!))" //定義した変数にタップされた日付を入れる print("date selected: \(dateFormatter.string(from: dayView.date!))") self.performSegue(withIdentifier: "next", sender: nil) }
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "next" { let writeViewController = segue.destination as! WriteViewController writeViewController.parameter = date } }
prepareではdateをdateという変数に入れます。このdateはwriteViewControllerに定義しているものです。
import UIKit class WriteViewController: UIViewController { var date = "" override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. print(parameter) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func save(_ sender: Any) { self.dismiss(animated: true, completion: nil) } }
ここのdateに画面遷移時に値をセットしているんですね。
relamに書いた内容を登録する
書いた日記を登録するために、Realmを使ってみます。 PodfileにRealmSwiftを追加しましょう。
8 # Pods for Diary 9 pod 'JBDatePicker' 10 pod 'RealmSwift'
pod install
これでRealmSwiftが入ったので、使っていけます。
書いた日記を司るクラスを作る。
NSObjectでDiaryという名前でファイルを作ります。
import UIKit import RealmSwift class Diary: Object { }
作ったファイルにimport RealmSwiftを記述し、NSObjectをOBjectに変更。buildしてみましょう。
うまくいかなかった場合、cleanしてからbuildしましょう。
import UIKit import RealmSwift class Diary: Object { dynamic var text = "" }
textという名前で、送信された文字を保存したいと思います。Realmを使用する際、プロパティにはdynamicをつけるルールみたいです。
textViewoutletで紐づけておきます。 紐づけたら、保存処理を行いましょう。
@IBAction func save(_ sender: Any) { let realm = try! Realm() let diary = Diary() diary.text = textView.text! try! realm.write { realm.add(diary) } self.dismiss(animated: true, completion: nil) }
returnボタンを押した時にキーボードを閉じるようにdelegateも設定しておきます。
class WriteViewController: UIViewController, UITextViewDelegate
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if (text == "\n") { //あなたのテキストフィールド textView.resignFirstResponder() return false } return true }
realmに保存した値を確認する。
Realm Browserをインストールします。 その後、以下の記事を参考に確認します。 https://qiita.com/ryoegu/items/3a7543a954673396d10d
@IBAction func save(_ sender: Any) { let realm = try! Realm() print(Realm.Configuration.defaultConfiguration.fileURL!) //ファイルパスを表示させる。 let diary = Diary() diary.text = textView.text! try! realm.write { realm.add(diary) } self.dismiss(animated: true, completion: nil) }
ターミナルに出るfile://から始まる文章がパスを表しています。
file:///Users/〇〇〇〇default.realm
これの/Users/〇〇〇〇default.realmまでコピーします。
open /Users/〇〇〇〇default.realm
コピーしたらターミナルに上記を打ち込む。すると、Realm Browserが立ち上がります。
「Allow」をクリックして表示してみます。
ちゃんと入力した値が入っていました。
値が入っていたら日付をタップした際にその値を表示させたいです。 ViewControllerを編集します。
override func viewDidLoad() { super.viewDidLoad() DispatchQueue(label: "background").async { let realm = try! Realm() if let savedDiary = realm.objects(Diary.self).filter("date == '\(self.date)'").last { let text = savedDiary.text DispatchQueue.main.async { self.textView.text = text } } } textView.delegate = self }
これで、日付をタップした際にRealmにデータがあれば取ってきて表示してくれます。