![]() | ![]() | ![]() |
---|---|---|
아이폰 SE | 아이폰 15 Pro | 아이폰 16 Pro |
alertHighlightView의 centerY를 Safe Area Insets 또는 Navigation Bar의 높이를 기준으로 설정하려 했으나, 특정 디바이스에서 값이 예상대로 동작하지 않았음.
앱에서 사용자 권한 설정을 요청하는 UIAlertController
를 표시하면서, 사용자에게 권한 요청을 강조하기 위해 alertHighlightView
와 화살표(arrowImageView
)를 알럿 주변에 배치하려고 했다. 그러나 디바이스와 화면 크기마다 알럿의 위치가 다르기 때문에 정확히 alertHighlightView
의 centerY
를 계산하는 데 어려움을 겪었다.
permissionView.alertHighlightView.snp.makeConstraints {
$0.centerY.equalToSuperview().offset(-100)
}
alertHighlightView
의 위치가 알럿과 겹치거나, 너무 멀리 떨어지는 문제가 발생.permissionView.alertHighlightView.snp.makeConstraints {
$0.centerY.equalToSuperview().offset((navigationController?.navigationBar.frame.minY ?? 0) / 2)
}
alertHighlightView
를 배치.frame.minY
값이 0으로 반환되는 문제가 발생.permissionView.alertHighlightView.snp.makeConstraints {
$0.centerY.equalToSuperview().offset(view.safeAreaInsets.top / 2)
}
viewDidAppear
이전에는 safeAreaInsets
값이 0으로 반환되므로, 정확한 위치를 계산할 수 없음.UIAlertController가 렌더링된 후 실제 위치와 높이를 가져와 동적으로 alertHighlightView를 배치하는 방법으로 해결할 수 있었다.
![]() | ![]() |
---|---|
아이폰 SE | 아이폰 16 Pro |
alertHighlightView
의 위치를 동적으로 조정.alertHighlightView
가 항상 정확히 정렬.private func showPermissionSystemAlert() {
let alert = UIAlertController(
title: "'STAR' 앱이 스크린타임에 접근하려고 함",
message: """
'STAR'에 스크린타임 접근을 허용하면,
이 앱이 사용자의 활동 데이터를 보고,
콘텐츠를 제한하며, 앱 및 웹사이트의
사용을 제한할 수도 있습니다.
""",
preferredStyle: .alert
)
let denyAction = UIAlertAction(title: "허용 안 함", style: .cancel, handler: { _ in
self.navigateToStarList()
})
alert.addAction(denyAction)
let allowAction = UIAlertAction(title: "허용", style: .default, handler: { _ in
print("허용")
})
alert.addAction(allowAction)
alert.preferredAction = allowAction
/// 다크모드
if #available(iOS 13.0, *) {
alert.overrideUserInterfaceStyle = .dark
}
**present(alert, animated: true) {
let alertHeight = alert.view.frame.height
let alertCenterY = alert.view.frame.midY
self.permissionView.updateAlertHighlightViewY(alertCenterY: alertCenterY, alertHeight: alertHeight)
}**
}
func updateAlertHighlightViewY(alertCenterY: CGFloat, alertHeight: CGFloat) {
let screenHeight = UIScreen.main.bounds.height
let offset = alertCenterY - (screenHeight / 2)
alertHighlightView.snp.makeConstraints{
$0.centerY.equalToSuperview().offset(offset)
}
layoutIfNeeded()
}
alert.view.frame
값을 반영할 수 있었음present(alert, animated: true)
완료 핸들러 안에서 alert.view.frame
값을 읽으면 UIAlertController가 화면에 렌덜이된 후의 프레임을 가져온다고 함
그래서 시스템 알럿의 실제 높이와 중앙 Y 좌표를 계산할 수 있었음
문제 전: 알럿 렌더링 되기 전에 값을 읽으려 해서 해결이 안되었던 것 같음
문제 해결 후: 렌더링 완료 후의 값을 사용해서 정확한 높이와 중앙 Y좌표 값을 가져올 수 있었따.
screenHeight / 2
)이랑 시스템 알럿의 중앙(alertCenterY
) 간의 차이를 계산해, 그 차이를 offset
으로 정의 후 alertHighlightView
의 위치에 반영할 수 있었삼.centerY
제약 조건을 동적으로 업데이트하면서, 알럿과 alertHighlightView
의 상대적 위치를 일관되게 유지할 수 있었음.let offset = alertCenterY - (screenHeight / 2)
alertCenterY
시스템 알럿 중앙 좌표screenHeight / 2
화면의 중앙 좌표offset
시스템 알럿 중앙이 화면 중앙에서 얼마나 벗어나 있는지 계산… 첨부터 중앙에 있을 것이지…..updateAlertHighlightViewY
메서드 생성 후 alertHighlightView.snp.makeConstraints
를 다시 호출해, 기존 제약 조건에서 업데이트 해줌.alertHighlightView.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.width.equalTo(270 + 28)
$0.height.equalTo(195 + 28)
}
func updateAlertHighlightViewY(alertCenterY: CGFloat, alertHeight: CGFloat) {
let screenHeight = UIScreen.main.bounds.height
let offset = alertCenterY - (screenHeight / 2)
**alertHighlightView.snp.makeConstraints{
$0.centerY.equalToSuperview().offset(offset)
}**
layoutIfNeeded()
}
layoutIfNeeded()
로 즉시 적용layoutIfNeeded()
를 호출하여, 변경된 제약 조건을 즉시 화면에 반영함