Thank you for visiting our account. We are going to make a simple reminder app in an hour. If would you like to study yourself before hands-on, or review what you have learned in the session, please use the following material.
We are providing free hands-on on a monthly basis
https://www.meetup.com/iOS-Development-Meetup-for-Beginner/
Xcode 9 / Swift 4
Open Xcode
Select "Create a new Xcode project"
Select "Single View Application" and then tap "Next"
Fill "Product name" and then tap "Next"
Select the place for saving your project and then tap "Create"
1-1. Add 5 labels to the main view controller
Add 5 more labels to this view for "HH", "MM", "00:00", "Reminder title" and "details". Just like in the app picture.
1-2. Add two sliders to the view.
Add another slider for "MM" label. This time set maximum value to be 59
1-3. Add two texfields to the view.
Add another textfield under "Details:" label
1-4. Add a "Set reminder" button.
2-1. Connect outlets + actions
★ control + drag in storyboard to create a control segue
★ It's preferable to write following code yourself. It will help you to understand code more.
// Created by Sam on 2018-02-02.
// VERY IMPORTANT: DO NOT COPY/PASTE code to your app. Try following the lecture and writing the code yourself and look at available choices in each method you use. I have intentionally renamed a few things, so copy pasting will break your code.
import UIKit
import UserNotifications
class ViewController: UIViewController
{
@IBOutlet weak var remindAbout: UITextField!
@IBOutlet weak var details: UITextField!
@IBOutlet weak var timeDisplay: UILabel!
// We use global variables that can be accessed by all functions inside this class
var hour: Int = 0
var minute: Int = 0
var center: UNUserNotificationCenter!
override func viewDidLoad()
{
super.viewDidLoad()
// Assign UITextFieldDelegates to both UITetFields. We want them to dismiss keyboard when their return key is pressed.
// It is required for our ViewController to adopt UITextFieldDelegate protocol. So we have done it in the extension section below.
remindAbout.delegate = self
details.delegate = self
// Get an instance of our device notification center
center = UNUserNotificationCenter.current()
center.delegate = self
// Each time the app opens and is directed to this view we want to check if the application has permissions to send notifications
center.requestAuthorization(options: [.alert, .badge, .sound])
{ (granted, error) in
if granted
{
print("We have access to notifications.")
// We can use this to enabled a previously disabled "Set reminder" button so user can now set a notification. Otherwise they shouldn't be able to do it. We are not implementing it for this lecture.
// You can do it as a challenge.
// Hint: connect the "set reminder" button to this view controller and on viewDidLoad disable the button
}
else
{
print("No permission to send notifications.")
// Show a msg or an alert that user needs to grant access to the app to send notifications.
// We wont cover it in this lecture. As a challenge try to implement it yourself.
// Hint: use UIAlertController: https://developer.apple.com/documentation/uikit/uialertcontroller
// Example: https://medium.com/ios-os-x-development/how-to-use-uialertcontroller-in-swift-70143d7fbede
}
}
}
// We are going to assign this method to BOTH of our sliders and we will differentiate them by their tags.
// Right click drag from BOTH sliders to this function.
@IBAction func sliderMoved(_ sender: UISlider)
{
// In the storyboard we have set the tags for each slider. Now we want to check which slider is making the call.
switch sender.tag
{
case 1:
self.hour = Int(sender.value)
default:
self.minute = Int(sender.value)
}
timeDisplay.text = "\(self.hour):\(self.minute)"
}
@IBAction func setReminder(_ sender: Any)
{
// Create the content thats going to be displayed to the user through the notification
let content = UNMutableNotificationContent()
content.title = "Reminder:"
content.body = "\(remindAbout.text ?? "")"
content.userInfo = ["details": "\(details.text ?? "")"]
content.sound = UNNotificationSound.default()
// We need this identifier tag to later add actions to this notification
content.categoryIdentifier = "Reminder"
// We are setting up some criteria's to match with for triggering the notification.
// Things you can look for include but not limited to year, month, day, hour, minute, second, nanosecond, weekday, weekOfMonth, weekOfYear, yearForWeekOfYear
var dateComponents = DateComponents()
dateComponents.hour = hour
dateComponents.minute = minute
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
// Add buttons (actions) to the notification.
let show = UNNotificationAction(identifier: "details", title: "Tell me more…", options: .foreground)
let goAway = UNNotificationAction(identifier: "fine", title: "Dismiss", options: .destructive)
// Now add these actions to the notification. The identifier should match the content's "categoryIdentifier"
let category = UNNotificationCategory(identifier: "Reminder", actions: [show, goAway], intentIdentifiers: [])
center.setNotificationCategories([category])
center.add(request)
}
}
extension ViewController: UNUserNotificationCenterDelegate
{
// Notification Center Delegate will handle responses. Following function will tell us what the user's response was so we can react to it accordingly.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
{
// Response has the user info which we created previously. There we can find our message and we can properly handle it.
let userInfo = response.notification.request.content.userInfo
if let details = userInfo["details"] as? String
{
print("Notification data received")
switch response.actionIdentifier
{
case UNNotificationDefaultActionIdentifier:
// the user swiped to unlock
print("Default identifier")
case "details":
// the action that user took was that he/she pressed on the "Tell me more..." button
print("Here are the details: \(details)")
break
default:
break
}
}
// you must call the completion handler when you're done
completionHandler()
}
}
extension ViewController: UITextFieldDelegate {
// Text Field Delegate handles actions associated with the UITextFields.
// Following method handles when the return button is clicked.
// In this case we just want the keyboard to dismiss.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}