UITableView top to topLayoutGuide以编程方式内容插入

时间:2014-11-19 18:56:35

标签: uitableview swift autolayout

由于我尝试“正确”实施iAd(即共享ADBannerView的单个实例),我在UITableView内以编程方式创建UIViewController并将其添加到视图。以下是我的UIViewController子类的几个片段:

来自viewDidLoad

self.tableView = UITableView(frame: self.view.bounds, style: .Grouped)
self.tableView.allowsSelectionDuringEditing = true
self.tableView.registerNib(UINib(nibName: "TableViewCellWithSwitch", bundle: nil), forCellReuseIdentifier: "SliderCellIdentifier")
self.tableView.dataSource = self
self.tableView.setTranslatesAutoresizingMaskIntoConstraints(false)

self.view.addSubview(self.tableView)
self.tableViewBottomLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute: .Top, multiplier: 1, constant: 0)
self.view.addConstraints([
    NSLayoutConstraint(item: self.tableView, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1, constant: 0),
    //NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0),
    //NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: self.topLayoutGuide.length),
    //NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0),
    NSLayoutConstraint(item: self.tableView, attribute: .Right, relatedBy: .Equal, toItem: self.view, attribute: .Right, multiplier: 1, constant: 0),
    self.tableViewBottomLayoutConstraint
    ])
// This must be called or the use of self.topLayoutGuide will not function
// See: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html#//apple_ref/occ/instp/UIViewController/topLayoutGuide
self.view.layoutSubviews()

iAds实施(添加以尝试和证明,正确或错误地,我对UITableView的实施)

func showiAds(animated: Bool) {
    println("Show iAd")
    if !self.showingiAd {
        println("Showing iAd")
        self.showingiAd = true

        // Add the banner view below the content before it's then animated in to view
        let delegate = UIApplication.sharedApplication().delegate as AppDelegate
        let bannerView = delegate.bannerView
        self.bannerBottomConstraint = NSLayoutConstraint(item: bannerView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute: .Top, multiplier: 1, constant: bannerView.frame.size.height)

        if (bannerView.superview != self.view) {
            bannerView.removeFromSuperview()
        }
        self.view.addSubview(bannerView)
        self.view.addConstraints([
            self.bannerBottomConstraint,
            NSLayoutConstraint(item: bannerView, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: bannerView, attribute: .Right, relatedBy: .Equal, toItem: self.view, attribute: .Right, multiplier: 1, constant: 0),
            ])
        self.view.layoutIfNeeded()


        // Only the changing of the value of the top of the banner is animated so it "slides in" from the bottom
        self.bannerBottomConstraint.constant = 0
        self.view.setNeedsUpdateConstraints()
        UIView.animateWithDuration(animated ? 0.5 : 0, animations: { () -> Void in
            // Calling layoutIfNeeded here will animate the layout constraint cosntant change made above
            self.view.layoutIfNeeded()
            }, completion: { (completed) -> Void in
                if completed {
                    println("Completed animation")
                }
        })
    }
}

func hideiAds() {
    println("Hide iAd")
    if self.self.showingiAd {
        self.showingiAd = false
        println("Hiding iAd")
        let delegate = UIApplication.sharedApplication().delegate as AppDelegate
        let bannerView = delegate.bannerView
        if bannerView.superview == self.view {
            bannerView.removeFromSuperview()
        }
        self.view.removeConstraint(self.tableViewBottomLayoutConstraint)
        self.tableViewBottomLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute: .Top, multiplier: 1, constant: 0)
        self.view.addConstraint(self.tableViewBottomLayoutConstraint)
    }
}

如您所见,有3个约束被注释掉了。这些中的每一个似乎都有不同的结果。我不会发布它们的截图(除非要求),但我会描述它们。

NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0)

iOS 7:表格顶部和表格内容位于屏幕顶部。内容位于导航栏后面

iOS 8:表格顶部和表格内容位于导航栏下方。内容位于导航栏下方(正确

NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: self.topLayoutGuide.length)

iOS 7:表格顶部和表格内容位于屏幕顶部。内容位于导航栏后面

iOS 8:表格顶部和表格内容位于导航栏下方。内容位于导航栏下方(正确

NSLayoutConstraint(item: self.tableView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0)

iOS 7:表格顶部和表格内容位于导航栏下方。内容位于导航栏下方(正确

iOS 8:表格的顶部位于导航栏的底部(正确),但表格的内容位于导航栏下方,再加上(看起来像是什么)偏移量的高度(的不正确

我知道我可以做一个if iOS7 {...} else {...},但感觉非常脏,我感觉这是我缺乏理解导致这个问题,所以我想弄清楚如何如果可能的话,无需借助版本检查就可以在iOS 7和8上完成这项工作。

1 个答案:

答案 0 :(得分:0)

我最终找到了这样做的方法。我不确定它有多酷,但它到目前为止在iOS 7.0-8.2上有效。

override func viewDidLayoutSubviews() {
        if self.tableView != nil {
            // Setting both of these to 0 seems to fix some auto layout issues that crop up in iOS 7/8 depending on
            // which item the layout is to, e.g., in iOS 8, having the UITableView's top be to the topLayoutGuide's bottom will
            // cause a gap at the top of the UITableView, but this removes that gap and doesn't seem to affect iOS 7
            self.tableView.contentInset = UIEdgeInsetsZero
            self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero

            if self.showingiAd {
                let delegate = UIApplication.sharedApplication().delegate as AppDelegate
                if let bannerView = delegate.bannerView {
                    let bannerViewHeight = bannerView.frame.size.height
                    self.tableViewBottomLayoutConstraint.constant = -bannerViewHeight
                }
            }
        }
    }