目次
- カレンダーアプリを作ろう!
- 使用したもの
- 事前準備
- Realmを使う
- FSCalendar&CalculateCalendarLogicを使う
- スケジュール登録機能を追加する
- 完成
- 感想
- 参考文献
カレンダーアプリを作ろう!
今回はFSCalendar + Realmを使って、スケジュール登録ができるカレンダーアプリを作ってみました。
使用したもの
Xcode9.3
Swift4.1
CocoaPods
FSCalendar
CalculateCalendarLogic
Realm
※尚、今回CocoaPodsの導入は割愛します。
事前準備
まず、CocoaPodsを使って、FSCalendarとCalculateCalendarLogicとRealmをインストールする。
ターミナルで、以下のコードを記入し実行。
pod init
これで、Podfileが生成される。
次に、Podfileを以下の様に編集する。
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'xxx' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# 以下の行を追加
pod 'RealmSwift'
pod 'FSCalendar'
pod 'CalculateCalendarLogic'
# 追加ここまで
# Pods for xxx
target 'xxxTests' do
# 以下略
そして、ターミナルで、
pod install
を実行する。
これで、インストール完了。
Realmを使う
まず、RealmでDB設定を行う。
今回は、
- 日付(date)
- スケジュール(event)
を登録する。
Command + N
キーを押す->iOS
->Source
からSwift File
を選択し、Swiftファイルを新規作成。
作成したSwiftファイルに、以下のコードを記述する。
import Foundation
import RealmSwift
class Event: Object {
@objc dynamic var date: String = ""
@objc dynamic var event: String = ""
}
これで、RealmのDB設定は完了。
FSCalendar&CalculateCalendarLogicを使う
次に、FSCalendar&CalculateCalendarLogicを使って、カレンダー機能を実装する。
簡単に説明すると、
- FSCalendar -> カレンダー機能を実装する
- CalculateCalendarLogic -> 土日・祝日の判定機能を実装する
という感じだ。FSCalendarには、祝日を判別する機能はないので、そこをCalculateCalendarLogicで補っている。
ViewController.swift
に以下のコードを記入。
import UIKit
import FSCalendar
import CalculateCalendarLogic
import RealmSwift
//ディスプレイサイズ取得
let w = UIScreen.main.bounds.size.width
let h = UIScreen.main.bounds.size.height
class ViewController: UIViewController, FSCalendarDelegate, FSCalendarDataSource, FSCalendarDelegateAppearance {
//スケジュール内容
let labelDate = UILabel(frame: CGRect(x: 5, y: 580, width: 400, height: 50))
//「主なスケジュール」の表示
let labelTitle = UILabel(frame: CGRect(x: 0, y: 530, width: 180, height: 50))
//カレンダー部分
let dateView = FSCalendar(frame: CGRect(x: 0, y: 30, width: w, height: 400))
//日付の表示
let Date = UILabel(frame: CGRect(x: 5, y: 430, width: 200, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
//カレンダー設定
self.dateView.dataSource = self
self.dateView.delegate = self
self.dateView.today = nil
self.dateView.tintColor = .red
self.view.backgroundColor = .white
dateView.backgroundColor = .white
view.addSubview(dateView)
//日付表示設定
Date.text = ""
Date.font = UIFont.systemFont(ofSize: 60.0)
Date.textColor = .black
view.addSubview(Date)
//「主なスケジュール」表示設定
labelTitle.text = ""
labelTitle.textAlignment = .center
labelTitle.font = UIFont.systemFont(ofSize: 20.0)
view.addSubview(labelTitle)
//スケジュール内容表示設定
labelDate.text = ""
labelDate.font = UIFont.systemFont(ofSize: 18.0)
view.addSubview(labelDate)
//スケジュール追加ボタン
let addBtn = UIButton(frame: CGRect(x: w - 70, y: h - 70, width: 60, height: 60))
addBtn.setTitle("+", for: UIControlState())
addBtn.setTitleColor(.white, for: UIControlState())
addBtn.backgroundColor = .orange
addBtn.layer.cornerRadius = 30.0
addBtn.addTarget(self, action: #selector(onClick(_:)), for: .touchUpInside)
view.addSubview(addBtn)
}
fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian)
fileprivate lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
// 祝日判定を行い結果を返すメソッド
func judgeHoliday(_ date : Date) -> Bool {
//祝日判定用のカレンダークラスのインスタンス
let tmpCalendar = Calendar(identifier: .gregorian)
// 祝日判定を行う日にちの年、月、日を取得
let year = tmpCalendar.component(.year, from: date)
let month = tmpCalendar.component(.month, from: date)
let day = tmpCalendar.component(.day, from: date)
let holiday = CalculateCalendarLogic()
return holiday.judgeJapaneseHoliday(year: year, month: month, day: day)
}
// date型 -> 年月日をIntで取得
func getDay(_ date:Date) -> (Int,Int,Int){
let tmpCalendar = Calendar(identifier: .gregorian)
let year = tmpCalendar.component(.year, from: date)
let month = tmpCalendar.component(.month, from: date)
let day = tmpCalendar.component(.day, from: date)
return (year,month,day)
}
//曜日判定
func getWeekIdx(_ date: Date) -> Int{
let tmpCalendar = Calendar(identifier: .gregorian)
return tmpCalendar.component(.weekday, from: date)
}
// 土日や祝日の日の文字色を変える
func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
//祝日判定をする
if self.judgeHoliday(date){
return UIColor.red
}
//土日の判定
let weekday = self.getWeekIdx(date)
if weekday == 1 {
return UIColor.red
}
else if weekday == 7 {
return UIColor.blue
}
return nil
}
}
スケジュール登録機能を追加する
まず、スケジュール登録ページ(EventViewController.swift
)を追加する。
Command + N
キーを押す->iOS
->Source
からCocoa Touch Class
を選択し、新規作成。
そして、Main.StoryBoard
にView Controller
を追加し、
Custom Class
のclass
をEventViewController
にする。
そして、各StoryBoard IDを以下の様にする。
ViewController -> Main
EventViewController -> Insert
まずは、画面遷移を実装する。
ViewController.swift
に以下のコードをclass内に追加する。
//画面遷移(スケジュール登録ページ)
@objc func onClick(_: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let SecondController = storyboard.instantiateViewController(withIdentifier: "Insert")
present(SecondController, animated: true, completion: nil)
}
次に、スケジュール登録ページを実装する。
以下のコードをEventViewController.swift
に記入。
import UIKit
import RealmSwift
//ディスプレイサイズ取得
let w2 = UIScreen.main.bounds.size.width
let h2 = UIScreen.main.bounds.size.height
//スケジュール内容入力テキスト
let eventText = UITextView(frame: CGRect(x: (w2 - 300) / 2, y: 100, width: 300, height: 200))
//日付フォーム(UIDatePickerを使用)
let y = UIDatePicker(frame: CGRect(x: 0, y: 300, width: w2, height: 300))
//日付表示
let y_text = UILabel(frame: CGRect(x: (w2 - 300) / 2, y: 570, width: 300, height: 20))
class EventViewController: UIViewController {
var date: String!
override func viewDidLoad() {
super.viewDidLoad()
//スケジュール内容入力テキスト設定
eventText.text = ""
eventText.layer.borderColor = UIColor.gray.cgColor
eventText.layer.borderWidth = 1.0
eventText.layer.cornerRadius = 10.0
view.addSubview(eventText)
//日付フォーム設定
y.datePickerMode = UIDatePickerMode.date
y.timeZone = NSTimeZone.local
y.addTarget(self, action: #selector(picker(_:)), for: .valueChanged)
view.addSubview(y)
//日付表示設定
y_text.backgroundColor = .white
y_text.textAlignment = .center
view.addSubview(y_text)
//「書く!」ボタン
let eventInsert = UIButton(frame: CGRect(x: (w2 - 200) / 2, y: 600, width: 200, height: 50))
eventInsert.setTitle("書く!", for: UIControlState())
eventInsert.setTitleColor(.white, for: UIControlState())
eventInsert.backgroundColor = .orange
eventInsert.addTarget(self, action: #selector(saveEvent(_:)), for: .touchUpInside)
view.addSubview(eventInsert)
//「戻る!」ボタン
let backBtn = UIButton(frame: CGRect(x: (w - 200) / 2, y: h - 50, width: 200, height: 30))
backBtn.setTitle("戻る", for: UIControlState())
backBtn.setTitleColor(.orange, for: UIControlState())
backBtn.backgroundColor = .white
backBtn.layer.cornerRadius = 10.0
backBtn.layer.borderColor = UIColor.orange.cgColor
backBtn.layer.borderWidth = 1.0
backBtn.addTarget(self, action: #selector(onbackClick(_:)), for: .touchUpInside)
view.addSubview(backBtn)
}
//画面遷移(カレンダーページ)
@objc func onbackClick(_: UIButton) {
dismiss(animated: true, completion: nil)
}
//日付フォーム
@objc func picker(_ sender:UIDatePicker){
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd"
y_text.text = formatter.string(from: sender.date)
view.addSubview(y_text)
}
//DB書き込み処理
@objc func saveEvent(_ : UIButton){
print("データ書き込み開始")
let realm = try! Realm()
try! realm.write {
//日付表示の内容とスケジュール入力の内容が書き込まれる。
let Events = [Event(value: ["date": y_text.text, "event": eventText.text])]
realm.add(Events)
print("データ書き込み中")
}
print("データ書き込み完了")
//前のページに戻る
dismiss(animated: true, completion: nil)
}
}
DBに書き込んだ値を取得し、カレンダーに反映させる。
Viewcontroller.swift
に以下のコードを追加する。
//カレンダー処理(スケジュール表示処理)
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition){
labelTitle.text = "主なスケジュール"
labelTitle.backgroundColor = .orange
view.addSubview(labelTitle)
//予定がある場合、スケジュールをDBから取得・表示する。
//無い場合、「スケジュールはありません」と表示。
labelDate.text = "スケジュールはありません"
labelDate.textColor = .lightGray
view.addSubview(labelDate)
let tmpDate = Calendar(identifier: .gregorian)
let year = tmpDate.component(.year, from: date)
let month = tmpDate.component(.month, from: date)
let day = tmpDate.component(.day, from: date)
let m = String(format: "%02d", month)
let d = String(format: "%02d", day)
let da = "\(year)/\(m)/\(d)"
//クリックしたら、日付が表示される。
Date.text = "\(m)/\(d)"
view.addSubview(Date)
//スケジュール取得
let realm = try! Realm()
var result = realm.objects(Event.self)
result = result.filter("date = '\(da)'")
print(result)
for ev in result {
if ev.date == da {
labelDate.text = ev.event
labelDate.textColor = .black
view.addSubview(labelDate)
}
}
}
問題なければ、ここで完成。
完成
感想
思ってたより、大変でした。
スケジュール登録機能が凄く大変でした。
Realmが全然ダメダメだったので、勉強する必要がありますね。。。。
参考文献
Swiftで簡単にカレンダーを作ろう!(FSCalendar)
Swiftで日記アプリを作ろう 〜その3 Realm活用編〜