撫養 航 - 備忘録

SEの備忘録

Xcode

設計

・懸念点

・初回起動時のログイン作業を避ける ・外観の整合性をとる ・操作の一環性 ・直接操作させる ・操作のフィードバック ・メタファを使用(UIを現実世界のものに例える) ・ユーザの望ましくない操作を回避 ​

AppleiPhoneアプリ方針

・控えめであること ・明瞭であること ・奥行きを与えること ​

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)
            }
        }
    }