2017-02-16 1 views
0

"Best Practice"에 대해 읽고/배우는 중에도 매우 익숙하지 만 간단한 코드를 리팩토링하려하지만 옵션을 중심으로 머리를 감싸고 간단한 UICollectionView을 배치하는 데 어려움을 겪고 있습니다. UIViewController.UIViewController 콜렉션 뷰 선택적인 언 래핑 크래시

나는 나가에서 "모범 사례"를 적용하려고 원하기 때문에 내가 이렇게이

class AddFriendsController: UIViewController { 

    fileprivate let cellId = "cellId" 
    private weak var collectionViewTest: UICollectionView? 
    private weak var layout: UICollectionViewFlowLayout? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel)) 

     layout = UICollectionViewFlowLayout() 
     layout!.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 
     layout!.itemSize = CGSize(width: 111, height: 111) 

     collectionViewTest = UICollectionView(frame: self.view.frame, collectionViewLayout: layout!) 
     collectionViewTest!.delegate = self 
     collectionViewTest!.dataSource = self 
     collectionViewTest!.register(UserFriendCell.self, forCellWithReuseIdentifier: cellId) 

     view.addSubview(collectionViewTest!) 
     collectionViewTest!.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 
     collectionViewTest!.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 
     collectionViewTest!.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true 
     collectionViewTest!.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true 
    } 

    @objc private func handleCancel() { 

     self.dismiss(animated: true, completion: nil) 
    } 
} 

extension AddFriendsController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 

    func numberOfSections(in collectionView: UICollectionView) -> Int { 

     return 2 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 

     return 9 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! UserFriendCell 

     return cell 
    } 
} 

처럼되고 싶은

class AddFriendsController: UIViewController { 

    fileprivate let cellId = "cellId" 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel)) 

     let layout = UICollectionViewFlowLayout() 
     layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 
     layout.itemSize = CGSize(width: 111, height: 111) 

     let collectionViewTest = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) 
     collectionViewTest.delegate = self 
     collectionViewTest.dataSource = self 
     collectionViewTest.register(UserFriendCell.self, forCellWithReuseIdentifier: cellId) 

     view.addSubview(collectionViewTest) 
     collectionViewTest.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 
     collectionViewTest.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 
     collectionViewTest.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true 
     collectionViewTest.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true 
    } 

    @objc private func handleCancel() { 

     self.dismiss(animated: true, completion: nil) 
    } 

} 

extension AddFriendsController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 

    func numberOfSections(in collectionView: UICollectionView) -> Int { 

     return 2 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 

     return 9 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! UserFriendCell 

     return cell 
    } 
} 
작동하는, 무엇을 가지고 스위프트를 배우면서 시작하십시오. 즉,이 경우에 이해 한 것부터 시작하여 가능한 한 많은 것을 만들어야합니다. private weak ify/"optionalize"뷰/아웃렛을 사용하여 c를 유지하지 마십시오. ycles.

문제

앱이 layout!.sectionInset 레벨에서 무을 풀기 때문에 강타 충돌.

나에게 기꺼이 좋은 영혼이 있습니까?

미리 감사드립니다.

+0

왜 재산 약한 레이아웃입니까? 뷰 컨트롤러를 유지하고 있습니까? 선언문에서 초기화하지 않으시겠습니까? 그래서 당신은 unwrap을 강요 할 필요가 없습니다. : UICollectionViewFlowLayout = UICollectionViewFlowLayout = UICollectionViewFlowLayout() –

답변

2

레이아웃이 약하다고 판단하는 것 같습니다. 강하게 변경하면 취약한 부분 만 제거하면 괜찮을 것입니다.

CollectionView와 같습니다.

또한 스타일의 문제로 매번 언 랩핑하지 않고 레이아웃과 콜렉션 뷰를 암시 적으로 언 래핑하도록 선언 할 수 있습니다.

그래서 코드와 문제 private var layout: UICollectionViewFlowLayout!

+0

또한 콜렉션 뷰에서 weak를 제거해야합니다.이 뷰가 생성 되었기 때문에 IBOutlet을 만들 때 weak를 사용해야하고 storyboard/xib에 계속 있어야합니다! –

+0

잘 작동합니다. @ 크리스, 감사합니다! @Vadim ok는 내 주된 심문이었습니다. '약한보기'는 스토리 보드에서 UI를 디자인 할 때만 필요하지만 방금 인용 한 이유 때문에 프로그래밍 방식으로는 필요하지 않습니다. 즉, 내 경우에는 아무 것도 지적하지 않으면 안전하게 할당 해제됩니다. ? 다른 컨트롤러'controllerB'에서'collectionViewTest'에 대한 참조가 있다면 :'controllerB'를 닫을 때 유지주기를 피하기 위해'controllerB'에서이 참조를'weak'으로해야합니까? – Herakleis

0

같은 것이 있습니다.

당신이

private weak var layout: UICollectionViewFlowLayout? 

같은 옵션과 같이 변수를 복용하는 경우는 그 전에 강제이 아닌 전무 있는지 확인해야 풀다. 그래서이 줄에서 실제로 강제 변수가 아닌 변수를 강제로 제거하려고 시도하기 때문에 충돌이 발생합니다.

layout!.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 

그래서 nil이 아닌 체크를 추가하지 않고 원하는대로 작성하려면 작성해야합니다.

layout?.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 

그러나 여기 약한 참조는 ARC에 의해 해제되는 객체를 보호하지 않는 개체에 단지 포인터이기 때문에 당신이 약한 변수를 가지고 가면 안된다 때문에 코드도 잘못된 것입니다.

여기 UIViewController의 수명주기를 통해 UICollectionViewFlowLayout 및 UICollectionView를 사용하여 약하게 만들지 않아야합니다.

그래서 두 가지를 모두 아래에 정의해야합니다.

private var collectionViewTest: UICollectionView! 
    private var layout: UICollectionViewFlowLayout! 

또는

private var collectionViewTest: UICollectionView? 
    private var layout: UICollectionViewFlowLayout? 
+0

세부 사항을위한 감사합니다 @ Nikunj – Herakleis

+0

그것은 나의 즐거움이다 :) –

관련 문제