2017-05-08 11 views
5

게으른 var 초기화를 사용할 때이 UIBarButtonItem 대상 문제가 무의식적으로 발견되었습니다.iOS 게으른 var UIBarButtonItem 대상 문제

class ViewController: UIViewController { 
    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action1)) 
    lazy var barButtonItem2: UIBarButtonItem = { 
    let barButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action2)) 
    return barButtonItem 
    } 

    override func viewDidLoad() { 
    super.viewDidLoad() 

    print(barButtonItem1.target, barButtonItem2.target) 
    } 
} 

인쇄 결과는 barButtonItem1.target은 전무였다, 그리고 barButtonItem2.target 미친 것 자체였다! barButtonItem1의 게으른 var 쓰기를 사용할 때이 문제가 발생하고 barButtonItem1의 액션을 호출 할 수 없다는 것을 알았고 마지막으로 barButtonItem1.target은 nil이라는 문제가있었습니다.

나는 왜 이런 일이 일어날 지 모르지만, 이것이 꽤 버그라고 확신합니다. 누구든지 이것에 대해 알고 있나요? 당신이 그것에 대해 설명 할 수 있다면 정말 고마워 할 것입니다.

+1

난 당신이 barButtonItem1' 제대로 '일을하는지 생각하지 않습니다. 첫 번째'lazy var'는 데이터 타입으로 선언되어야합니다. 둘째로, 당신은 단지 그것을 정규 var처럼 값으로 설정하는 것입니다. https : //www.hackingwithswift를 읽으십시오.com/example-code/language/what-are-lazy-variables – thedp

+0

barButtonItem1의 선언은 [link] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language)에 따라 정확해야합니다. /Properties.html). – user5685969

+1

[link] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)에 따르면 barButtonItem1의 선언이 정확해야합니다. 그러나 나는 당신이 barButtonItem1에 대한 데이터 형식 선언을 추가했다는 것을 시도해 보았습니다. 나는 아직도이 원인을 모른다. – user5685969

답변

3

다음은 내 생각에입니다. 그리고 불행히도, 나는 의견을 말할 충분한 명성이 없으므로 대답을 해 줄 것입니다.

제 생각에는 이것은 컴파일러 버그입니다.


먼저 UIBarButtonItem의 작은 확장을 만들었습니다.

extension UIBarButtonItem { 
    convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, targetViewController: UIViewController?, action: Selector?) { 
     // call the initializer provided by UIKit 
     self.init(barButtonSystemItem: systemItem, target: targetViewController, action: action) 
    } 
} 

그럼 I 아래 코드와 지연 저장된 변수를 초기화하려고 (두번째 파라미터 Any?하지만 UIViewController?이 아닌).

class ViewController: UIViewController { 

    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     print(barButtonItem1.target) 
    } 
    func action() { } 
} 

그런 다음 '(NSObject의) ->() ->의 ViewController'제기 오류를 컴파일러 및

유형의 값을 변환 할 수 없습니다 말 예상 인수 유형 '의 UIViewController?'

이는 컴파일러가 selfViewController임을 확인하지 못했음을 나타냅니다. (두 번째 파라미터 Any?의 때문에 UIKit 제공하는 이니셜 형 (NSObject) ->() -> ViewController 값을 받아들이는 컴파일 할 것이다.)

그러나

lazy var barButtonItem1: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

소스 코드와 같은 지연 변수에 환원 형 주석 게 컴파일 barButtonItem1.targetself으로 설정되었습니다.

필자는 형식 주석이 컴파일에 도움이되었다고 생각합니다. 위의 이유는 내가 직면 한 문제가 컴파일러 버그로 인한 것 같아요.


은 참조 : 당신이 직면 한 문제와 유사이보고 된 문제를. 둘 다 컴파일러 버그로 결론 지었다.

Swift lazy instantiating using self

Type inference when using lazy instantiation

+0

고마워요! 그래서 이것은 정말로 컴파일러 버그입니다, 희망 사과는 곧 그것을 고칠 것입니다. 지금은 유형 주석을 추가해 보겠습니다. – user5685969