2016-08-21 7 views
2

새로 고침 할 때에 프로퍼티 방법을 찾고 있지만 UINavigationBar (참조 : How to properly refresh a UINavigationBar?를) 나는이 질문에 건너 온 : 이것은 갱신선택적 체인과 선택적 바인딩 : 사용할 때?

UINavigationBar 의도 한대로, 비록없는 깨끗한 방법 : 그러나

if let navigationController = self.navigationController { 
    navigationController.popViewControllerAnimated(false) 
    navigationController.pushViewController(self, animated: false) 
} 

현재 뷰 컨트롤러를 팝하지만 밀어 내지 않습니다 :

navigationController?.popViewControllerAnimated(false) 
navigationController?.pushViewController(self, animated: false) 

이 동작을 어떻게 설명 할 수 있습니까?

+0

내비게이션 컨트롤러가없는 특정 컨트롤러에 상황이 있습니까? 이 속성은 선택 사항이지만 항법 컨트롤러 (Interface Builder에서)가 항상있는 경우 안전하게 포장 풀기 할 수 있습니다. – vadian

답변

2

선택적 바인딩은 바인딩중인 것을 변수에 저장합니다. 이 경우 navigationController입니다.

한편, 선택 체인은 변수의 왼쪽에있는 값을 넣지 않습니다. 단지라고 말합니다

물음표의 왼쪽에있는이 값이 nil인지 여부를 확인합니다. 그렇지 않은 경우 나머지 식을 계산하십시오. 이 경우, 뷰 컨트롤러 (첫 번째 줄), self.navigationController이 전무가되고 두 ​​번째 줄의 메서드 호출이 때문에 평가되지 않습니다 튀어 그래서 후에 전무

로 평가.

self.navigationController이 될 않는 무기 호 : 이러한 혼란이있을 수 있습니다

?

하나의 가능성은 selfnavigationController의 평면도 컨트롤러이다. self이 터지면 모든 탐색 컨트롤러에 속하지 않습니다.

선택적 바인딩이 작동하지만 선택 체인이 작동하지 않는 이유는 무엇입니까?

앞에서 말한 것처럼 선택 바인딩은 self.navigationController의 값을 변수 navigationController에 넣습니다. 따라서 self.navigationController이 nil 인 경우에도 navigationController은 그 값을 유지합니다.

2

선택적 바인딩을 사용하면 모든 논리 블록을 매번 같은 방식으로 사용할 수 있습니다. 선택 체인의 여러 행은 예상치 못한 동작을 일으킬 수있는 경쟁 조건에 잠재적으로 영향을받을 수있는 상황을 정확히 모호하게 만들 수 있습니다.

선택적 바인딩을 사용하면 방금 래핑하지 않은 항목에 대한 새 참조가 만들어지고 일반적으로 강력한 참조가됩니다. 다른 경우의 돌연변이를 일으키지 않는 지역 참고 자료이기도합니다. 습관에 의해 일반적으로 let입니다. 그래서 그것은 평생 동안 같은 가치를 유지할 것입니다.

예를 들어 보겠습니다. 그러나 약간 조정하십시오.탐색 컨트롤러은 (its 내비게이션 적층 새 view 컨트롤러 추가 해당보기를 컨트롤러 오프 불쑥시 pushViewController)으로 그것이 itself으로 동등한 view 컨트롤러의 navigationController 속성 전달으로 설정. 그리고 because as

if let navigationController = self.navigationController { 

    // this should always pass 
    assert(navigationController === self.navigationController) 

    navigationController.popViewControllerAnimated(false) 

    // this next assert may fail if `self` refers to the top VC on the nav stack 
    assert(navigationController === self.navigationController) 

    // we now add self back onto the nav stack 
    navigationController.pushViewController(self, animated: false) 

    // this should also always pass: 
    assert(navigationController === self.navigationController) 
} 

는 happening is 스택, 그것은 nil 다시 그 속성을 설정

의 다시 이러한 주장을 던지고, 옵션 - 체인 방식을 살펴 보자.

let navController = navigationController 

// this should always pass 
assert(navController === navigationController) 

// assuming navigationController does not evaluate to nil here 
navigationController?.popViewControllerAnimated(false) 

// this may fail if `self` is top VC on nav stack 
assert(navController === navigationController) 

// if above failed, it's because navigation controller will now evaluate to nil 
// if so, then the following optional chain will fail and nothing will happen 
navigationController?.pushViewController(self, animated: false) 

// if the previous assert fail, then the previous push wasn't called 
// and if the previous push wasn't called, then navigation controller is still nil 
// and therefore this assert would also fail: 
assert(navController === navigationController) 

을 그래서 여기, 우리의 채소를 self의 nce 속성이 nil으로 설정되어 있습니다.이 메서드 호출은 선택적인 바인딩 & 체인 간의 동작 차이를 일으 킵니다.

비록 우리가 현재 스레드에서 우리 자신의 행동으로 돌연변이를 일으키지 않았더라도 이전에 유효한 값을 가지고 있더라도 갑자기 속성이 nil으로 평가되는 문제를 해결할 수 있습니다. 다중 스레드 코드를 사용하여 다른 스레드에서 값이 nil으로 또는 그 반대로 평가되는 속성이 발생할 수 있습니다.

간단히 말해서 all-or-none을 확인해야하는 경우 선택적 바인딩을 선호해야합니다.