250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- react
- 비전공자
- 애니메이션
- xcode
- jQuery
- front-end
- 자바스크립트
- SWIFT
- css3
- html5
- hover
- effect
- 프론트엔드
- iOS 개발자
- CSS
- HTML
- keyframes
- Animation
- 백엔드
- php
- iPhone
- MAC
- 개발자
- button
- javascript
- 비전공 개발자
- IOS
- ipad
- 풀스택
- image
Archives
- Today
- Total
비전공자 개발일기
Local Push Notification 본문
728x90
SMALL
import UIKit
class AddAlertViewController: UIViewController {
var pickedDate: ((_ date: Date) -> Void)?
@IBOutlet weak var datePicker: UIDatePicker!
@IBAction func cancelBTN(_ sender: UIBarButtonItem) {
dismiss(animated: true)
}
@IBAction func saveBTN(_ sender: UIBarButtonItem) {
pickedDate?(datePicker.date)
dismiss(animated: true)
}
}
import Foundation
struct Alert:Codable {
var id: String = UUID().uuidString
let date: Date
var isOn: Bool
var time: String {
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "h:mm"
return timeFormatter.string(from: date)
}
var meridiem: String {
let meridiemFormatter = DateFormatter()
meridiemFormatter.dateFormat = "a"
meridiemFormatter.locale = Locale(identifier: "en_US_POSIX")
return meridiemFormatter.string(from: date)
}
}
import UIKit
import UserNotifications
class AlertListCell: UITableViewCell {
var userNofiticationCenter = UNUserNotificationCenter.current()
override class func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@IBOutlet weak var meridiemLabel: UILabel!
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var alertSwitch: UISwitch!
@IBAction func alertSwitchToggle(_ sender: UISwitch) {
guard let data = UserDefaults.standard.value(forKey: "alerts") as? Data,
var alerts = try? PropertyListDecoder().decode([Alert].self, from: data) else { return }
alerts[sender.tag].isOn = sender.isOn
UserDefaults.standard.set(try? PropertyListEncoder().encode(alerts), forKey: "alerts")
if sender.isOn {
userNofiticationCenter.addNotificationRequest(by: alerts[sender.tag])
} else {
userNofiticationCenter.removePendingNotificationRequests(withIdentifiers: [alerts[sender.tag].id])
}
}
}
import UIKit
import UserNotifications
class AlertListViewController: UITableViewController {
var alerts: [Alert] = []
var userNofiticationCenter = UNUserNotificationCenter.current()
override func viewDidLoad() {
super.viewDidLoad()
let nibName = UINib(nibName: "AlertListCell", bundle: nil)
tableView.register(nibName, forCellReuseIdentifier: "AlertListCell")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
alerts = alertList()
}
@IBAction func addAlertBTN(_ sender: UIBarButtonItem) {
guard let addAlertViewControll = storyboard?.instantiateViewController(identifier: "AddAlertViewController") as? AddAlertViewController else { return }
addAlertViewControll.pickedDate = { [weak self] date in
guard let self = self else { return }
var alertList = self.alertList()
let newAlert = Alert(date: date, isOn: true)
alertList.append(newAlert)
alertList.sort { $0.date < $1.date }
self.alerts = alertList
UserDefaults.standard.set(try? PropertyListEncoder().encode(self.alerts), forKey: "alerts")
self.userNofiticationCenter.addNotificationRequest(by: newAlert)
self.tableView.reloadData()
}
present(addAlertViewControll, animated: true)
}
func alertList() -> [Alert] {
guard let data = UserDefaults.standard.value(forKey: "alerts") as? Data,
let alerts = try? PropertyListDecoder().decode([Alert].self, from: data) else { return [] }
return alerts
}
}
// UITableView Datasource, Delegate
extension AlertListViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return alerts.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return " 🚰 Time to drink water!"
default:
return nil
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "AlertListCell", for: indexPath) as? AlertListCell else { return UITableViewCell() }
cell.alertSwitch.isOn = alerts[indexPath.row].isOn
cell.timeLabel.text = alerts[indexPath.row].time
cell.meridiemLabel.text = alerts[indexPath.row].meridiem
cell.alertSwitch.tag = indexPath.row
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
// Remove Notification
self.alerts.remove(at: indexPath.row)
UserDefaults.standard.set(try? PropertyListEncoder().encode(self.alerts), forKey: "alerts")
userNofiticationCenter.removePendingNotificationRequests(withIdentifiers: [alerts[indexPath.row].id])
self.tableView.reloadData()
return
default:
break
}
}
}
import UIKit
import NotificationCenter
import UserNotifications
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// var userNofiticationCenter: UNUserNotificationCenter?
var userNofiticationCenter = UNUserNotificationCenter.current()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
let authrizationOptions = UNAuthorizationOptions(arrayLiteral: [.alert, .badge, .sound])
userNofiticationCenter.requestAuthorization(options: authrizationOptions) {_, error in
if let error = error {
print("Error: Notification authrization request \(error.localizedDescription)")
}
}
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
extension AppDelegate:UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .list, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler()
}
}
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
UIApplication.shared.applicationIconBadgeNumber = 0
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
import Foundation
import UserNotifications
extension UNUserNotificationCenter {
func addNotificationRequest(by alert: Alert) {
let content = UNMutableNotificationContent()
content.title = "This is time to drink water💧"
content.body = "The recommended daily water intake by the WHO is 1.5 to 2 liters👨🏻💼"
content.sound = .default
content.badge = 1
let component = Calendar.current.dateComponents([.hour, .minute], from: alert.date)
let trigger = UNCalendarNotificationTrigger(dateMatching: component, repeats: alert.isOn)
let request = UNNotificationRequest(identifier: alert.id, content: content, trigger: trigger)
self.add(request)
}
}
728x90
LIST
'SWIFT' 카테고리의 다른 글
Xylophone (0) | 2022.12.23 |
---|---|
Real Time Notice' s modal (Firebase Remote Config & A/B Test) (0) | 2022.12.20 |
Remote Push Notification(APNs, FCM) (0) | 2022.12.19 |
Diary (0) | 2022.12.18 |
Status of COVID-19 outbreak(CocoaPods, Alamfire, Charts) (0) | 2022.12.17 |