UIViewController中的集合视图可选解包崩溃

时间:2017-02-16 10:51:06

标签: ios swift uiviewcontroller swift3 uicollectionview

对于Swift来说还是一个非常新的并且已经阅读/了解了“最佳实践”,我试图重构一些简单的代码,但是无法绕过选项并在{{1}中放置一个简单的UICollectionView }}

我拥有的,有效的

UIViewController

我想要的是什么

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
    }
}

这样做是因为我想在学习Swift时尝试从一开始就应用“最佳实践”,即从我在这种情况下理解的内容尽可能多地创建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 } } private ify / “自定义”视图/出口以避免保留周期。

问题

应用程序崩溃是因为在weak级别打开了一个nil。

有什么好心的人愿意开导我吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

看起来你正在宣布你的布局很弱。如果你将它改为强,即只是删除弱,那么你应该没问题。

您的CollectionView也是如此。

另外,作为一种风格问题,你可以声明你的布局和你的collectionView被隐式展开而不是每次展开。

类似于private var layout: UICollectionViewFlowLayout!

答案 1 :(得分:0)

您的代码存在问题。

如果您将变量视为可选项,如

 private weak var layout: UICollectionViewFlowLayout?

然后在强行打开之前,你应该确认这是非零的。所以在这一行它会导致崩溃,因为你正试图强行打开一个实际为零的变量。

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

所以,如果你想这样做而不添加非零检查而不是你应该写的。

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

但是这里你的代码也是错误的,因为你不应该变弱,因为弱引用只是一个指向对象的指针,它不能保护对象不被ARC释放

在这里你需要UICollectionViewFlowLayout和UICollectionView整个UIViewController的生命周期,所以你不应该把它当作弱点。

所以你应该将两者都定义为。

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

OR

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