얼럿(Alert)?
화면에 경고 메세지를 표시하는 앱. 경고 확인 뿐만 아니라 두 가지 이상의 선택을 요구할 수 있고 특정 작업도 수행할 수 있음
import UIKit
class ViewController: UIViewController {
@IBOutlet var mainImg: UIImageView!
let eatSnow = UIImage(named: "snow1.JPG")
let spitSnow = UIImage(named: "snow2.JPG")
let imgCate = UIImage(named: "cat1.JPG")
var isEatSnow = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
mainImg.image = eatSnow
}
@IBAction func btnEat(_ sender: UIButton) {
if (isEatSnow == true){
let EatAlert = UIAlertController(title: "경고", message: "현재 먹는 상태입니다", preferredStyle: UIAlertController.Style.alert)
// 컨트롤러 생성
let onAction = UIAlertAction(title: "네, 알겠습니다", style: UIAlertAction.Style.default, handler: nil)
EatAlert.addAction(onAction) //onAction을 eatAlert에 추가
present(EatAlert, animated: true, completion: nil) //present 메서드 실행
}
else{
mainImg.image = eatSnow
isEatSnow=true
}
}
@IBAction func btnSpit(_ sender: UIButton) {
}
@IBAction func btnCat(_ sender: UIButton) {
}
@IBAction func btnSpit(_ sender: UIButton) {
if(isEatSnow){
let spitAlert = UIAlertController(title: "사람 뱉기", message: "사람을 뱉겠습니까?", preferredStyle: UIAlertController.Style.alert)
let spitAction = UIAlertAction(title: "네", style: UIAlertAction.Style.default, handler: {
ACTION in self.mainImg.image = self.spitSnow
self.isEatSnow=false
})
let cancelAction = UIAlertAction(title: "아니오", style: UIAlertAction.Style.default, handler: nil)
spitAlert.addAction(spitAction)
spitAlert.addAction(cancelAction)
present(spitAlert, animated: true, completion: nil)
}
}
alert 에 action 을 추가할때는 반드시 self 붙여야 함.
cf. 익명함수
func completWork (finished: Bool)
-> () {
print ("complete : \(finished)")
}
//Bool 타입의 finished 매개변수를 받아 출력하는 함수, 리턴 x
//익명 함수 형태로 바꿀 경우
{
(finished:Bool) -> in
print("complete : \(finished)")
}
// {(매개변수) -> (반환타입)in 실행구문}
//혹은 반환타입을 미리 설정해둔 경우 생략도 가능
{
(finished:Bool) in
print("complete: \(finished)")
}
//(매개변수) in 실행구문
Reference to property 'spitSnow' in closure requires explicit use of 'self' to make capture semantics explicit
-> 해결방법 : self 등 정확한 지칭 붙여주기
...
정상작동
@IBAction func btnCat(_ sender: UIButton) {
let removeSnow = UIAlertController(title: "눈 제거", message: "눈사람을 치울까요?", preferredStyle: UIAlertController.Style.alert)
let offAction = UIAlertAction(title: "아니요, 뱉습니다.", style: UIAlertAction.Style.default, handler: {
ACTION in self.mainImg.image = self.spitSnow
self.isEatSnow=false
})
let onAction = UIAlertAction(title: "아니요, 먹습니다.", style: UIAlertAction.Style.default) {
ACTION in self.mainImg.image = self.eatSnow
self.isEatSnow = true
}
//핸들러 매개변수 없이 뒤에 넣어도 정상적으로 작동.
let removeAction = UIAlertAction(title:"네, 고양이 보여주세요.", style: UIAlertAction.Style.destructive, handler: {
ACTION in self.mainImg.image = self.imgCat
self.isEatSnow = false
})
removeSnow.addAction(offAction)
removeSnow.addAction(onAction)
removeSnow.addAction(removeAction)
present(removeSnow, animated: true, completion: nil)
}
action 에서 default 스타일과 destructive 스타일의 차이도 확인 가능
도전! 알람시계 만들기
현재 시간이 선택한 시간과 같아지면 얼럿으로 알람 메세지를 만드는 알람 시계를 만들어 보세요.
-조건
[네, 알겠습니다]를 누른 후에는 1분동안 알람 창이 나타나지 않게 설정
1차 시도
import UIKit
class ViewController: UIViewController {
@IBOutlet var lbTimeNow: UILabel!
@IBOutlet var lbTimeSelect: UILabel!
@IBOutlet var datePickerView: UIDatePicker!
let timeSector: Selector = #selector(ViewController.updateTime)
let interval = 1.0
var alarmTime:String?
var currentTime:String?
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(timeInterval: interval, target: self, selector: timeSector, userInfo: nil, repeats: true) //여기서 0.1마다 timeSectior라고 정의된 updateTime 함수를 호출하는 것!!!
}
@IBAction func pickedDateChanged(_ sender: UIDatePicker) {
let datePickerView = sender //datePickerView 라는 상수에 UIDatePicker의 자료형 인수 (sender)가 저장됨.
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm aaa"
alarmTime = formatter.string(from: datePickerView.date)
lbTimeSelect.text = alarmTime
checkTime()
}
@objc func updateTime (){
let date = NSDate() // 현재 시간을 NSDate 함수를 통해서 가져옴
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm aaa"
currentTime = formatter.string(from: date as Date)
lbTimeNow.text=currentTime
checkTime()
}
@objc func checkTime () {
print("checkTime call : \(currentTime ?? "없"), \(alarmTime ?? "없")")
if(alarmTime == currentTime){
let timerAlert = UIAlertController(title: "알림", message: "설정된 시간입니다!", preferredStyle: UIAlertController.Style.alert)
let alertAnswer = UIAlertAction(title: "네, 알겠습니다.", style: UIAlertAction.Style.default, handler:{
// 1분동안 울리지 않으려면? 방법 1. interval을 조절한다.
// 단점: 다시 조정해 줘야 함, let 에서 var 로 바꿔야 함.
//ACTION in self.interval = 60.0
//방법 2. 그냥 alarmTime을 변경 ( 어차피 선택시간은 datePicker 가 변경될 때 표시)
//
Action in self.alarmTime = ""
})
timerAlert.addAction(alertAnswer)
present(timerAlert, animated: true, completion: nil)
}
}
}
제대로 기능은 하지만, 1초마다 확인할 필요는 없는 것 같다.
//기본 1초에 한 번 호출
@objc func updateTime (){
let date = NSDate() // 현재 시간을 NSDate 함수를 통해서 가져옴
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss EEE"
lbTimeNow.text="현재시간: "+formatter.string(from: date as Date) //라벨 표시 (1초마다)
formatter.dateFormat = "hh:mm aaa" //분으로 자르기
if(currentTime != formatter.string(from: date as Date)){
print("1분마다 체크하는지 확인")
currentTime = formatter.string(from: date as Date)
checkTime()
}
}
update time을 수정했다.
그리고 나서 생각해보니 두 가지 의문이 생겼다.
1. checkTime 함수를 매번 호출해서 확인하는게 효율적인가?
2. DateFormatter()를 매 함수마다 새로 변수로 만들어서 활용하는데, 전역 변수로 하나 만들어 두는게 효율적인거 아닌가?
1번은... interval 자체를 60초로 만들면 중간에? 지금 시간으로 변경하면 확인할 수가 없기 때문에 잘 모르겠고...
2번은 이전에 date picker 활용할 때 했던대로 그냥 생각 없이 했던 것인데, 아무래도 전역변수로 만드는게 효율적인 것 같다. 마지막으로 수정.
import UIKit
class ViewController: UIViewController {
@IBOutlet var lbTimeNow: UILabel!
@IBOutlet var lbTimeSelect: UILabel!
@IBOutlet var datePickerView: UIDatePicker!
let timeSector: Selector = #selector(ViewController.updateTime)
let interval = 1.0
var alarmTime:String?
var currentTime:String?
let formatter = DateFormatter()
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(timeInterval: interval, target: self, selector: timeSector, userInfo: nil, repeats: true) //여기서 0.1마다 timeSectior라고 정의된 updateTime 함수를 호출하는 것!!!
}
@IBAction func pickedDateChanged(_ sender: UIDatePicker) {
let datePickerView = sender //datePickerView 라는 상수에 UIDatePicker의 자료형 인수 (sender)가 저장됨.
formatter.dateFormat = "hh:mm aaa"
alarmTime = formatter.string(from: datePickerView.date)
formatter.dateFormat = "선택시간: "+"yyyy-MM-dd HH:mm EEE"
lbTimeSelect.text = formatter.string(from: datePickerView.date)
checkTime()
}
//기본 1초에 한 번 호출
@objc func updateTime (){
let date = NSDate() // 현재 시간을 NSDate 함수를 통해서 가져옴
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss EEE"
lbTimeNow.text="현재시간: "+formatter.string(from: date as Date) //라벨 표시 (1초마다)
formatter.dateFormat = "hh:mm aaa" //분으로 자르기
if(currentTime != formatter.string(from: date as Date)){
print("1분마다 체크하는지 확인")
currentTime = formatter.string(from: date as Date)
checkTime()
}
}
@objc func checkTime () {
// print("checkTime call : \(currentTime ?? "없"), \(alarmTime ?? "없")")
if(alarmTime == currentTime){
let timerAlert = UIAlertController(title: "알림", message: "설정된 시간입니다!", preferredStyle: UIAlertController.Style.alert)
let alertAnswer = UIAlertAction(title: "네, 알겠습니다.", style: UIAlertAction.Style.default, handler:{
// 1분동안 울리지 않으려면? 방법 1. interval을 조절한다.
// 단점: 다시 조정해 줘야 함, let 에서 var 로 바꿔야 함.
//ACTION in self.interval = 60.0
//방법 2. 그냥 alarmTime을 변경 ( 어차피 선택시간은 datePicker 가 변경될 때 표시)
//
Action in self.alarmTime = ""
})
timerAlert.addAction(alertAnswer)
present(timerAlert, animated: true, completion: nil)
}
}
}
끝!
'Study > Swift' 카테고리의 다른 글
[swift error] this class is not key value coding-compliant for the key btnReload. (0) | 2024.12.20 |
---|---|
[swift error] Cannot find type 'WKWebView' in scope (0) | 2024.12.20 |
[swift error] NSBundle principal class is nil because all fallbacks have failed (0) | 2024.12.19 |
[스위프트 기초] 5장 피커뷰 사용해보기 (1) | 2024.12.18 |
[스위프트 기초] 4장 데이트 피커 사용해보기 (0) | 2024.12.17 |
댓글