[TIL]07.31

rbw·2022년 7월 31일
0

TIL

목록 보기
37/97

UIKit과 DispatchQueue.main 의 관계

API로 정보를 텍스트로 하여 알림으로 보여주는 뷰를 구성하고 해당 뷰의 쉐도우를 준다고 가정할 때, 정보의 크기에 따라서 뷰의 크기가 달라지는데, 이때 쉐도우가 높이에 맞지않게 들어가는 경우가 일어난다.

이것의 이유로는, API로 정보를 받아오는 과정보다 쉐도우를 넣는 함수가 내부에서 먼저 실행되므로 크기가 맞지 않게 들어가는 것이다. 따라서 API를 사용하여 뷰의 크기가 달라지는 경우에는, 쉐도우를 넣는 함수를 API로 정보를 전부 다 불러오고 나서 호출이 되야 한다.

UI를 설정해주는 UIKit 시스템 함수인 updateConstraints()DispatchQueue.main.async를 통해 실행되기 때문에, mainQueue(serial) 안에서는 Queue에 들어간 순서대로 실행이 되지만, Queue에 들어 있지 않은 코드들과는 비동기적으로 수행되므로 실행 순서를 장담할 수 없슴니당

이러한 이유로, updateShadow() 라는 UI를 업데이트하는 함수는 메인큐에서 실행되어야 함다

DispatchQueue.main.async {
    self.updateShadow()
}

UIKit UI 구성시에 알아 두면 좋을 것들 ?

위치 및 크기 속성

위치 및 크기에 관한 것은 CoreGraphics를 사용합니당 UIKit 내부에 있으므로 별도로 추가하지 않아도 ㄱㅊ

  1. 위치 : CGPoint(x:y:) 왼쪽 상단이 원점 임다
  2. 크기 : CGSize(width:height)

Frame과 Bounds

제일 중요한 차이는 frame은 자기자신의 view를이동, bounds는 subview들을 반대 방향으로 이동 하는 것을 알아두면 되겠슴더

  1. Frame

이는 슈퍼뷰를 기준으로 해당 뷰의 크기나 위치를 표현한다고 합니다.

sizeview를 감싸는 크기를 정의함다. 회전해도 view의 크기는 동일하지만, Size는 커짐다

  1. Bounds

이는 자기자신을 기준으로 해당 뷰의 크기나 위치를 표현합니다

sizeview 자체 크기를 의미함다. 회전을 하여도 size가 변하지 않슴다.

이 친구의 핵심은, 해당 view가 이동하는 것이 아닌, subview들을 반대 방향으로 이동시킴당

마지막으로, frame이라는 것은 super view를 기준으로 배치하는 것을 명심해야 합니드, center속성도 역시 frame 기준 !

뷰 추가

self.view를 사용함다, 해당 뷰 컨트롤러에 등록된 Rootview를 가리킵니당

override func viewDidLoad() {
    btn = UIButton(type: .system)
    btn.frame = ...
    btn.setTitle(...)
    ...
    self.view.addSubViews(btn)
}

SearchController 서치바 위 아래 줄 제거

서치바 구현중에 아무리해도 서치바 위 아래에 있는 디바이더? 줄 같은걸 못 지워서 검색 하다가 찾은 코드 !

좋지만,,, 뒤에가 보이는 부분이 조금 error;; 미니멀로 해야할둣

// 맨 앞 부분에 넣을 SearchBar 변수명을 적어주면 된다.
UISearchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)

서치바 크기 조절

// 내부 폰트사이즈에 맞게 크기가 변함 
searchBar.searchTextField.font = UIFont.systemFont(ofSize: 14)

프레임 같은게 아닌 내부 폰트로 조절하면 사이즈가 변하는걸 알아버렸으 ~

dismiss하고 present 하는 경우

먼저 dismiss 직후에 바로 present하는 경우를 살펴보겠슴다

dismiss 함수의 클로저로 present를 하는 형식을 사용하고, present시에는 dismiss된 뷰가 아닌 dismiss 된 뷰를 불러준 뷰를 찾아서 변수에 지정한 후에 present를 걸어줘야한다.

조금 헷갈릴수도 있는데 코드를 보면 이해가 될거 같슴다.

// currentVC => FirstViewController
// self.dismiss를 실행하고, self.present를 하면 띄워줄 뷰가 없으므로 아래의 코드로 해야한다.
guard let pvc = self.presentingViewController else { return }

self.dismiss(animated: true) {
    pvc.present(SecondViewController(), animated: true, completion: nil)
}

다음방식은 rootViewController 까지 dismiss 하고 present 하는 방식입니다.

이 방식은 뷰 계층에 스택이 많이 쌓여있는 경우에 유용함니당

self.view.window?.rootViewController?.dismiss(animated: false, completion: {
    let homeVC = HomeViewController()
    homeVC.modalPresentationStyle = .fullScreen
    let sd = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
    sd.window?.rootViewController?.present(homeVC, animated: true)
})

만약 뷰 계층에 루트 뷰, A뷰, B뷰, C뷰 컨트롤러가 존재한다면 A,B,C 뷰컨트롤러를 없애고 HomeViewController 를 띄워줍니다. 뷰 계층이 좀 깔끔해지는 모습을 볼 수 있슴다.

커스텀 애니메이션 설정

제시되는 뷰 컨트롤러의 transitioningDelegate 속성이 유효한 객체를 포함하고 있을 때, UIkit은 직접 생성한 커스텀 애니메이터를 사용해 해당 뷰 컨트롤러를 제시함다.

프레젠테이션이 준비되면 UIKit은 커스텀 애니메이터 객체를 회수하기 위해 전환 딜리게이트의 animationControllerForPresentedController:presentingController:sourceController: 메소드를 호출함다.

객체가 사용이 가능하다면 다음 과정을 수행합니당

  1. UIKit은 상호 작용 애니메이터 객체가 사용이 가능한 경우를 살펴보기 위해 전환 딜리게이트의 interactionControllerForPresentation: 메소드를 호출합니다. 이 메소드가 nil을 반환하면, 사용자 상호작용 없이 애니메이션을 수행함다.
  2. 애니메이션 듀레이션을 가져오기 위해 애니메이터 객체의 transitionDuration 메소드 호출
  3. 애니메이션 시작하기 위한 적합한 메소드를 호출
    • 상호작용 애니메이션이 없는 경우 애니메이터 객체의 animateTransition: 호출
    • 있는 경우, 상호 작용 애니메이터 객체의 startInteractiveTransition: 메소드 호출
  4. 컨텍스트 전환 객체의 `completeTransition: 메소드 호출 위해 애니메이터 객체를 기다리고, 애니메이션이 끝난 후 커스텀 애니메이터가 이 메소드를 호출 (completion block에서 주로 이루어짐) 이 메소드 호출은 전환을 마무리하고 UIKit 에게 presentViewController:animated:completion: 메소드의 컴플리션 핸들러를 처리 할 수 있다는 것을 알려줌다. 또 애니메이터 객체의 animationEnded: 메소드 호출도 가능함을 알려줌

이제 뷰 컨트롤러를 해제 하는 시점의 단계입니다.

  1. UIKit은 전환 딜리게이트의 anumationControllerForDismissedController: 메소드를 호출
  2. 사용 가능한지 확인 위해 전환 딜리게이트의 interactionCntrollerForDismissal: 메소드 호출, 다음 단계는 위에 과정과 같습니다.

애니메이션이 마무리 되는 시점에 completeTransition: 메소드 호출은 필수적, UIKit은 전환 프로세스를 마무리하지 않고, 이 메소드를 호출할 때까지 앱에서 컨트롤을 반환함다


참조

https://minios.tistory.com/17

https://ios-development.tistory.com/111

https://developer-fury.tistory.com/56

https://velog.io/@panther222128/Presentations-and-Transitions#initiating-a-segue-programmatically

profile
hi there 👋

0개의 댓글