在UICollectionViewCell中使用Storyboard中的Autolayout约束

时间:2015-08-19 10:08:18

标签: ios swift autolayout uicollectionview uicollectionviewcell

我正在为UICollectionViewCell使用自定义UICollectionView课程。我必须在我的自定义类中使用addSubview,因为我使用的是FirebaseUI-iOS。这就是我的MessageCollectionViewCell的样子:

import Foundation
import UIKit
class MessageCollectionViewCell: UICollectionViewCell {
    @IBOutlet var messageContainerView: UIView?
    @IBOutlet var messageText: UILabel?
    @IBOutlet var messageDisplayName: UILabel?
    @IBOutlet var messageUserImage: UIImageView?
    @IBOutlet var messageUserImageOverlay: UIView?

    override init(frame: CGRect) {
        super.init(frame: frame)

        // Custom initialization code for label
        let size = self.contentView.frame.size
        let frame = CGRectMake(0.0, 0.0, size.width, size.height)

        self.messageContainerView = UIView(frame: frame)
        self.messageUserImageOverlay = UIView(frame: frame)
        self.messageText = UILabel(frame: frame)
        self.messageDisplayName = UILabel(frame: frame)

        self.messageContainerView!.addSubview(self.messageUserImageOverlay!)
        self.messageContainerView!.addSubview(self.messageText!)
        self.messageContainerView!.addSubview(self.messageDisplayName!)
        self.contentView.addSubview(messageContainerView!)
    }

    required init(coder aDecoder: NSCoder) {
        println("Init")
        super.init(coder: aDecoder)
    }
}

我的Storyboard文件中有我想要使用的约束,但是当我使用addSubview时,我的约束不会被使用。反正我是否可以使用addSubview()并仍然保留约束?我知道我可以通过编程方式添加它,但我希望使用我在Storyboard中设置的约束。

1 个答案:

答案 0 :(得分:1)

此问题是由于FirebaseUI' FirebaseCollectionViewDataSource`如何注册它的类。我不相信它可以像这样实例化一个类并从你喜欢的XIB中获取自动布局属性,但是可以通过修复我们的处理来解决问题。原型细胞。

这里的问题是我们要重复注册单元的reuseIdentifier两次:一次在故事板中,一次在代码中(FirebaseCollectionViewDataSource必须这样做才能使单元格出列)。因为我们称之为第二个,它会覆盖第一个,这意味着你的所有出口都没有填充,布局很奇怪等等。这意味着你必须设置它们就像使用常规子类而不是XIB一样。你在这里可以做的最快的事情就是使用XIB而不是原型单元(它只是故事板中的一个XIB)。那么,我们如何支持FirebaseUI +原型单元......

简短的回答是,由于Apple的UICollectionView设计,目前此功能无法实现。

UITableView不同,FirebaseTableViewDataSource可以通过将单元格出列(它将返回实例化的原型单元并告诉我们已经创建了reuseidentifier)来检查此行为,就像我们在UICollectionView {{中所做的那样3}},func dequeueReusableCellWithReuseIdentifier(_ identifier: String, forIndexPath indexPath: NSIndexPath!) -> AnyObject 没有提供类似的方法,它只给出:

indexPath

鉴于此方法需要一个NSInternalInconsistencyException,因为它来返回一个非零对象,当我们尝试读取任意对象时,它会抛出一个reuseIdentifier在初始化时(因为没有要读取的项目)。此外,似乎没有任何方法可以通过编程方式检查-registerClass: forReuseIdentifier:是否正在使用中。这给我们留下了一些选择:

  1. 建议人们不要使用原型单元格,而是使用自定义子类或XIB并将它们挂钩。故事板和原型单元感觉更脆弱(主要是出于这样的原因),但绝对容易使用它们。
  2. FirebaseCollectionViewDataSource中拨出FirebaseTableViewDataSource来电,虽然这意味着reuseIdentifier也应该更改(即使它可以正常工作)并让开发人员明确地调用它(或不在使用故事板的情况下)。
  3. 将故事板的参数添加到初始化调用中,该调用仍会保留NSException以使单元格出列,但不会注册该类。
  4. 尝试将单元格出列,捕获use std::collections::HashMap; type KeyCode = char; type CmdType = Fn(&mut E); struct E { key_map: HashMap<KeyCode, Box<CmdType>>, } impl E { fn map_key(&mut self, key: KeyCode, function: Box<CmdType>) { self.key_map.insert(key, function); } fn quit(&mut self) { println!("quitting"); /* ... */ } } fn main() { let mut e = E { key_map: HashMap::new() }; e.map_key('q', Box::new(|e: &mut E| e.quit())); match e.key_map.get(&'q') { Some(f) => f(&mut e), None => {} } } ,注册该类并重试。这样做有效,但它仍会抛出异常并在runloop中添加更多代码(我们必须使用try-catch包装调用,我们知道最多只会失败一次)。
  5. 我个人的偏好是1,但原型单元的价值主张足够高,3可能是这个库的最佳选择。我不愿意做2,因为细胞注册是一个很难解决的问题。

    目前,我建议使用XIB而不是原型单元,或者等待我们选择上述解决方案之一(我们可以很快推出一个版本来解决问题)。