Accessibility for UIKit

접근성 관련해서 잘 지원해주는 플랫폼 중 하나는 애플이다. 아래는 애플의 접근성 관련 설명 페이지

https://developer.apple.com/documentation/uikit/accessibility_for_uikit

 

Supporting VoiceOver in Your App

여러 접근성 중 보이스오버가 가장 많이 적용하는 것 중 하나일 것이다. 아래 페이지는 애플 가이드 페이지

https://developer.apple.com/documentation/uikit/accessibility_for_ios_and_tvos/supporting_voiceover_in_your_app

  • The accessibilityLabel property provides descriptive text that VoiceOver reads when the user selects an element.
  • The accessibilityHint property provides additional context (or actions) for the selected element.

 

Accessibility for iOS Developer Guide 

iOS 접근성 관련해서 정말 잘 설명되어있는 가이드 페이지! 

https://a11y-guidelines.orange.com/en/mobile/ios/development/

 

iOS developer guide - Orange digital accessibility guidelines

VoiceOver must vocalize every informative element with a high degree of quality in order to let the user know and perfectly understand the context of the consulted page. The accuracy of this vocalization is done through four attributes: label, hint, value

a11y-guidelines.orange.com

 

Raywenderlich의 Accessibility 가이드 페이지

https://www.raywenderlich.com/6827616-ios-accessibility-getting-started

 

iOS Accessibility: Getting Started

In this iOS accessibility tutorial, learn how to make apps more accessible using VoiceOver and the Accessibility inspector.

www.raywenderlich.com

https://www.raywenderlich.com/4720178-ios-accessibility-tutorial-making-custom-controls-accessible

 

iOS Accessibility Tutorial: Making Custom Controls Accessible

In this iOS accessibility tutorial, you’ll learn to make custom controls accessible using VoiceOver, elements group, custom action, traits, frame and more.

www.raywenderlich.com

 

시뮬레이터에서 접근성 테스트 방법

XCode > Open Developer Tool > Accessibility Insepector

 

 


목차

  • UNUserNotificationCenter란?
  • Push Notification 사용 권한 요청
    1. UNUserNotificationCenterDelegate 채택
    2. Notification 권한 부여 요청
    3. APNS(Apple Push Notification Service)에 등록

 

UNUserNotificationCenter란?

앱과 앱 익스텐션에 대한 알림 관련 작업을 관리하기 위한 센트럴 오브젝트.
공유된 UNUserNotificationCenter 객체를 사용하여 앱과 앱 확장의 모든 알림 관련 동작을 관리한다.

 

Push Notification 사용 권한 요청 

알림에 응답하여 알럿을 표시하거나, 소리를 재생하거나, 앱 아이콘에 배지를 달 수 있는 권한을 요청하는 방법에 대해 알아보자.

 

1. UNUserNotificationCenterDelegate 채택

알림 관련 작업을 처리하려면 UNUserNotificationCenterDelegate 프로토콜을 채택하는 객체를 생성하여 이 객체의 델리게이트 프로퍼티에 할당한다. 이 작업은 해당 델리게이트와 상호작용을 할 수 있는 다른 작업을 수행 하기 전에 이 델리게이트 프로퍼티에 객체를 항상 할당하자.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }
}

 

2. Notification 권한 부여 요청

승인을 요청하려면, UNUserNotificationCenter 인스턴스를 가져와서 requestAuthorization(options:completionHandler:) 을 호출하자. (alert, sound, badge 타입 요청 가능)

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
    
    if let error = error {
        // Handle the error here.
    }
    
    // Enable or disable features based on the authorization.
}

 

3. APNS(Apple Push Notification Service)에 원격 알림을 수신하도록 등록

Apple Push Notification Service에 등록 프로세스를 시작하려면 아래 메소드를 호출하자. (Main Thread에서 진행해야함.)

DispatchQueue.main.async {
    UIApplication.shared.registerForRemoteNotifications()
}

등록이 성공되었다면, 앱은 앱 델리게이트 객체의 application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 메소드를 호출하여 디바이스 토큰을 전달함. (디바이스의 원격 알림을 생성하기 위해서는 서버에 이 토큰을 전달해야함.)

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
}

등록이 실패되었다면, 앱은 앱 델리게이트 객체의 application(_:didFailToRegisterForRemoteNotificationsWithError:) 메소드를 호출한다.

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
}

 

 

Ref.

C언어 기반의 프로그래밍 언어에서는 main이라는 함수가 앱의 시작이 된다.
iOS 앱 또한 Objective-C 기반에서 돌아가기 때문에 앱은 main 함수에서 시작된다.

 

iOS 애플리케이션 실행 순서

  1. main 함수 실행
  2. main 함수에서 UIApplicationMain 함수 실행 (앱의 본체에 해당하는 객체인 UIApplication 객체 생성)
  3. Info.plist 파일을 읽어들여 파일에 기록된 정보를 참고하여 그 외에 필요한 데이터 로드.
    (Main nib 파일을 사용하는 경우 이 과정에서 로드됨.)
  4. Main nib 파일이 없거나 그 속에서 앱 델리게이트가 없는 경우, 앱 델리게이트 객체를 만들고 앱 객체와 연결.
  5. 런루프를 만드는 등 실행에 필요한 준비를 마무리함.
  6. 실행 완료를 앞두고, 앱 객체가 앱 델리게이트에게 application:didFinishLaunchingWithOptions: 메시지를 보냄.

Objective-C 기반 iOS 프로젝트 main.m 파일

 

UIApplicationMain 함수: 앱 로딩 프로세스

파라미터

  • principalClassName: 앱 객체가 될 클래스 이름. nil이면 UIApplication으로 대체
  • appDelegateClassName: 앱 델리게이트 클래스 이름.

기능

  • 앱의 본체에 해당하는 객체인 UIApplication 객체 생성, 이 객체는 앱의 Life Cycle 관리
  • 지정된 클래스(@UIApplicationMain이 표시된)에서 델리게이트를 인스턴스화 하고 이를 앱의 객체에 할당
  • 앱의 Run Loop를 포함한 기본 이벤트처리 루프를 설정하고 이벤트 처리 시작
  • 앱의 info.plist에 불러올 main nib 파일이 명시되어있으면, 해당 nib 파일을 불러옴.

 

 

이제 @main에 대해 알아보자.

 Swift 기반으로된 iOS 프로젝트는 main 파일이 없다. 그이유는?
@main을 선언하여 iOS 앱의 진입점을 컴파일러가 합성하기 때문.

@main을 선언해줌으로써, UIKit 앱의 진입점은 해당 클래스이고, 시스템은 UIApplicationDelegate 프로토콜에 구현되어있는 정적 main() 함수를 호출함.

 

(추가) Swift 5.3부터 프로그램의 entry point를 알려주는 속성이 @UIApplicationMain에서 @main으로 변경됨.

 

Ref.

Autolayout을 왜 사용해야하나?

: 모든 기기와 아이패드의 멀티태스킹을 지원하기 위해 불가피해지게 되었음.

 

Auto Layout Engine이 어떻게 뷰를 그리는지 알아보자.

Auto layout은 두가지 input을 사용한다: 

1) View Constraint 2) App Screen size

 

 

 

WWDC 2015 Mysteries of Auto Layout, Part1

Layout Engine은 모든 constraints를 취하여 Alignment Rects를 계산하고, 그에 따라 실제로 우리의 뷰를 배치한다

1) 뷰의 사이즈 제약사항

2) 제약사항의 우선순위, 컨첸츠 우선순위 (content hugging, compression resistence)

3) 정렬 - 수평 정렬, 수직 정렬, baseline 정렬

 

Build the layout

자세하게 살펴보자.

1. Activate and Deactivate

Constraints find their own container

Adds constraints efficiently
Do not need to own all views

 

Changing Constraints

Never deactivate self.view.constraints

Keep references to constraints
Animate changing constraints with view animation

 

2. View Sizing - Sizing Constraints 

  • 특정 뷰는 intrinsicContentSize를 가지고 있음 (UILableView, UIImageView, ...)
  • Constraint는 View의 size를 정의함.
  • Self-Sizing View는 Constraint들로부터 온전한 사이즈를 결정함 (예: UITableViewCell height size)

 

3. Priorities - constraint priorities, content priorities

Summary

- Can help keep constraints from unsatisfiability => But look out for competing priorities!

- Results are more consistent

- Use content priorities to get to the right layout => Hugging priorities hug content, Compression resistance resists squishing

 

왜 이런 Ambiguity 현상이 일어날까?

- Not enough constraints

- 일치(equal)하거나 필요가 충족되지 않은(non-required) priorities

 

Constraint priorities

- Priorities go from 1–1000  (Required is 1000, DefaultHigh is 750, DefaultLow is 250)

- Highest priority wins

 

Content priorities

- 뷰의 컨텐츠를 처리하는 방법 

- By default, these are not set as required. (Content needs to be able to move a little bit)

     : Do not set as required

     : Can cause unsatisfiable constraints

- Equal priorities can cause ambiguity

- Types

  • Content hugging priorities

  • Compression resistance priorites
    : this is how much a view resists its content getting squished.

 

 

4. Alignment - horizontal alignment, vertical alignment, baseline alignment

Aligning Baselines

Use firstBaseline and lastBaseline

firstBaseline / lastBaseline

Leading and Trailing

- Use leading/trailing instead of left/right

- Helps with prep for localization

 

Alignment Rects

Alignment rects are important because it's what the engine actually calculates.

The engine takes all of your constraints, calculates the alignment rects, and uses them to actually layout your views.

 

- Usually (not always) same as frame

- Includes the critical content only

- Does not change when view is transformed

- Override alignmentRectInsets if needed

- Find out the calculated rects (Use Show Alignment Rectangles in Debug menu)

- Get using alignmentRectForFrame:

 

Finally!!!!

 

 

 

Content Hugging Priority vs. Content Compression Resistance Priority

Ref. https://m.blog.naver.com/PostView.nhn?blogId=jdub7138&logNo=220963551062&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

 

// view.setContentHuggingPriority(.required, for: .horizontal)

 

 

 

Ref.

https://developer.apple.com/videos/play/wwdc2015/218/

https://medium.com/@shantakokateit/how-auto-layout-engine-calculates-ui-components-frame-c617fc9c94ae

+ Recent posts