設計
・懸念点
・初回起動時のログイン作業を避ける ・外観の整合性をとる ・操作の一環性 ・直接操作させる ・操作のフィードバック ・メタファを使用(UIを現実世界のものに例える) ・ユーザの望ましくない操作を回避
・AppleのiPhoneアプリ方針
・控えめであること ・明瞭であること ・奥行きを与えること
・MVCパターン
データ(Model)
なし ↓↑instance
処理(Controller)
IBOutlet↓↑IBAction
表示(View)
・アプリのライフサイクル
読み込み前 > loadView
読み込み後 > viewDidLoad ... 最初に一度だけ行いたい処理
(別画面から遷移)
表示前 > viewWillAppear
レイアウト前 > viewWillLayoutSubviews
レイアウト後 > viewDidLayoutSubviews
(画面表示開始)
表示後 > viewDidAppear
・・・
消える前 > viewWillDisappear
(画面表示終了)
消えた後 > viewDidDisappear
(別画面へ遷移)
Swift
segue
・戻ってきた時
@IBAction func ファンクション名(_ segue: UIStoryboardSegue) { // 処理 }
・別クラスをインスタンス化
let 変数 = segue.destination as! 別クラス名
タイマー
・宣言
// タイマー var timer: Timer! // 時間 var timer_sec: Float = 0
・始動
インターバル秒毎にselecterで指定した以下の関数を実行する
self.timer = Timer.scheduledTimer(timeInterval: インターバル秒, target: self, selector: #selector(関数名(_:)), userInfo: nil, repeats: true)
@objc func updateTimer(_ timer: Timer) { // ラベルに(インターバル秒毎に)経過時間を表示する self.timer_sec += インターバル秒 self.ラベル名.text = String(format: "%.1f", self.timer_sec) }
・タイマー停止
self.timer.invalidate()
日時フォーマット
// 取得 let formatter = DateFormatter() // 指定 formatter.dateFormat = "yyyy-MM-dd HH:mm" // 変換 let 変数:String = formatter.string(from: 変換するデータ)
通知
・AppDelegateに記述
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // ユーザに通知の許可を求める let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in // Enable or disable features based on authorization } center.delegate = self // フォアグラウンド時に通知を受け取る場合は記述 return true }
フォアグラウンド時に通知を受け取る場合は デリゲート「UNUserNotificationCenterDelegate」を追加して以下を記述
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .list, .sound]) }
.badge ... アプリアイコンに通知件数表示 .alert ... 通知バナー表示 .sound ... 通知音
・登録
以下はローカル通知を登録する処理
// 通知のインスタンス let content = UNMutableNotificationContent() content.title = task.title //タイトル content.body = task.contents //詳細 content.sound = UNNotificationSound.default //通知 // ローカル通知が発動するtrigger(日付マッチ)を作成 let calendar = Calendar.current let dateComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: task.date) let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false) // identifier, content, triggerからローカル通知を作成(identifierが同じだとローカル通知を上書き保存) let request = UNNotificationRequest(identifier: String(task.id), content: content, trigger: trigger) // ローカル通知を登録 let center = UNUserNotificationCenter.current() center.add(request) { (error) in print(error ?? "ローカル通知登録成功) } // 未通知のローカル通知一覧をログ出力 center.getPendingNotificationRequests { (requests: [UNNotificationRequest]) in print("未通知のローカル通知一覧") for request in requests { print("/---------------") print(request) print("---------------/") } }
・削除
Realm
・宣言
クラス外
import RealmSwift
クラス内
let realm = try! Realm() var realmSample = try! Realm().objects(Sample.self).sorted(byKeyPath: "date", ascending: true)
・segue で画面遷移時
override func prepare(for segue: UIStoryboardSegue, sender: Any?){ let inputViewController:InputViewController = segue.destination as! InputViewController if segue.identifier == "cellSegue" { let indexPath = self.tableView.indexPathForSelectedRow inputViewController.task = taskArray[indexPath!.row] } else { let task = Task() let allTasks = realm.objects(Task.self) if allTasks.count != 0 { task.id = allTasks.max(ofProperty: "id")! + 1 } inputViewController.task = task } }
UITableVeiwデリゲート
// データの数(=セルの数)を返すメソッド func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return taskArray.count // ←修正する } // 各セルの内容を返すメソッド func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 再利用可能な cell を得る let cell = tbl_sample.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) // Realmから情報を取得 let task:Task = realmSample[indexPath.row] // Cellに値を設定 cell.textLabel?.text = task.title cell.detailTextLabel?.text = task.date return cell } // 各セルを選択した時に実行されるメソッド func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { performSegue(withIdentifier: "cellSegue",sender: nil) } // セルが削除が可能なことを伝えるメソッド func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath)-> UITableViewCell.EditingStyle { return .delete } // Delete ボタンが押された時に呼ばれるメソッド func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // データベースから削除 try! realm.write { self.realm.delete(self.taskArray[indexPath.row]) tableView.deleteRows(at: [indexPath], with: .fade) } } }