UIAlertAction을 사용하면서 어떤 버튼을 눌렀을 때 UIAlertAction을 그 함수 내에서 설정하여 addAction()하는 경우로만 사용했었는데 필요한 Actions를 미리 프로퍼티로 저장해둔 후 추후 미리 만들어둔 UIAlertAction을 전달하여 UIAlertController로 띄우는 방법을 사용해보게 되었다.
var myActions: [UIAlertAction] = []
먼저 내가 저장할 액션 배열을 클래스 내 프로퍼티로 미리 선언해둔다.
private func setupAlertActions() {
let action1 = UIAlertAction(title: "action1", style: .default, handler: { _ in
print("select action1")
})
let action2 = UIAlertAction(title: "action2", style: .default, handler: { _ in
print("select action2")
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
myActions.append(action1)
myActions.append(action2)
myActions.append(cancel)
}
미리 액션 배열 프로퍼티에 UIAlertAction을 추가한다.
나는 이 함수를 viewDidLoad() 부분에서 실행하였다.
private func showAlertAction() {
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .actionSheet)
myActions.forEach { action in
alert.addAction(action)
}
present(alert, animated: true)
}
그리고 추후 미리 만들어둔 myActions를 alert에 추가하여 present한다.
나는 이 함수를 어떤 버튼을 눌렀을 때 실행하도록 설정하였다.
그러나 예상과 다른 부분이 있었다.
1. 처음 showAlertAction()을 실행했을 때
처음 showAlertAction()을 실행했을 때 handler에 주소값이 할당되어 있어 정상적으로 hander가 실행된다.
그래서 select action1 이 콘솔에 찍히는 것을 확인할 수 있었다.
2. 두번 이상 showAlertAction()을 실행했을 때
그러나 두번 이상 showAlertAction()을 실행했을 때 handler의 주소값이 초기화되어 hander가 더이상 작동하지 않는다.
사진에서는 0번째 데이터만 handler가 초기화 되었지만 다른 action데이터의 handler가 모두 초기화된다.
title같은 이외의 데이터는 그대로 값이 저장되어 있는 것을 보아 아마 handler는 참조형식이고, UIActionViewController 내에서 전달받은 UIAlertAction의 handler의 주소값을 초기화 해주는 것 같다.
애플의 의도는 정확하게 알지 못했지만 아무튼 배열로 액션을 따로 저장해둔 후 필요할 때 마다 present하는 방식은 내 의도처럼 작동하기는 힘들었다.
사용하기 직전에 action을 alert에 add 해주는게 애플에서 의도한 사용 방법인 것 같아 다음부터 사용할 때는 직전에 값을 add 해 주어야 겠다.
그러나 어거지로 해서 handler의 주소값이 초기화 되지 않게 할 수 있을 것 같아 이 부분도 한번 시도해 보았다.
private func showAlertAction() {
let alert = UIAlertController(title: "title", message: "message", preferredStyle: .actionSheet)
myActions.forEach { action in
// copy() 한 값을 add
alert.addAction(action.copy() as! UIAlertAction)
}
present(alert, animated: true)
}
이렇게 addAction()하는 데이터를 copy()를 통해 복사한 값을 add한다.
이렇게 하면 copy()를 통해 얕은 복사한 값을 add하게 된다.
두 이미지가 같긴 한데 첫 번째 사진은 최초 실행, 두 번째 사진은 그 이후 실행 했을 때 값이다.
copy를 한 함수와 안 한 함수를 번갈아서 테스트 했을 때 copy를 하지 않은 함수를 실행했을 때 최초 실행때는 handler의 주소값이 할당되어 있지만 그 이후에는 copy를 한 함수든 아니든 handler의 주소값이 초기화 된 것으로 보아 copy를 하지 않으면 최초 실행때만 handler가 있고, 그 때 handler의 주소값이 초기화 되는 것같다.
근데 의문인건 handler를 깊은 복사를 해야 주소값이 초기화가 되지 않을 것 같았는데 얕은 복사 만으로도 초기화가 안되는 것으로 봐서 어떤식으로 handler가 초기화 되는 건지 잘 모르겠다ㅠ
나중에 지식이 더 쌓이면 알게되기룰..🥲
참고 자료
https://stackoverflow.com/questions/66613771/uialertaction-not-reusable
'iOS' 카테고리의 다른 글
[iOS] Coordinator Pattern (1) | 2024.02.14 |
---|---|
[iOS/RxSwift] subscribe, bind, drive 비교하기 (0) | 2024.01.21 |
[iOS/RxSwift] Merge, CombineLatest, Zip 비교하기 (0) | 2024.01.20 |
[iOS] NIB View 생성자로 인스턴스 생성하기 (BaseView, 클린코드 독후감..) (1) | 2023.11.27 |
[iOS] CollectionView Pagination과 Kingfisher로 이미지 캐싱(Kakao Search Image API) (0) | 2023.10.24 |