Jos*_*ffy 2 uitableview ios iad
编辑
感谢@LeoNatan,我现在有了一个完整的工作解决方案.如果有人发现这个并想要解决方案,它可以在GitHub上找到.
原始问题
我正在尝试将iAds(或任何其他视图,尽管它可能是特定的ADBannerView)显示在a上方UITabBar.我已经采用了几种不同的方法来做到这一点,但还没有提出满足以下条件的解决方案:
UITableViews insets正确更新我迄今已工作的唯一解决方案一直有我的UITableView里面UIViewController,并添加UITableView和ADBannerView到view的财产UIViewController.我离开了这个有两个原因:
UITableView没有底部下方延伸的边缘UITabBarUITableViewController,而不是UIViewController我bannerView在我AppDelegate和一个属性上有一个属性shouldShowBannerView来决定是否显示iAd,并共享一个实例.所述AppDelegate随后发送出去时成瘾者应显示或隐藏的通知(即,当IAD设备被加载,并在用户已支付以除去IADS).代码的"基础"如下:
func showiAds(animated: Bool) {
if !self.showingiAd {
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
if let bannerView = delegate.bannerView {
println("Showing iAd")
self.showingiAd = true
if (bannerView.superview != self.view) {
bannerView.removeFromSuperview()
}
// let bannersSuperview = self.view.superview! // Bottom inset incorrect
let bannersSuperview = self.view // Banner is shown at the top screen. Crashes on iOS 7 (at bannersSuperview.layoutIfNeeded())
// let bannersSuperview = self.tableView // The is the same as self.view (duh)
// let bannersSuperview = self.tabBarController!.view // Bottom inset incorrect
// Added the view and the left/right constraints allow for the proper height
// to be returned when bannerView.frame.size.height is called (iOS 7 fix mainly)
bannersSuperview.addSubview(bannerView)
bannersSuperview.addConstraints([
NSLayoutConstraint(item: bannerView, attribute: .Left, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Left, multiplier: 1, constant: 0),
NSLayoutConstraint(item: bannerView, attribute: .Right, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Right, multiplier: 1, constant: 0),
])
bannersSuperview.layoutIfNeeded()
let bannerViewHeight = bannerView.frame.size.height
var offset: CGFloat = -self.bottomLayoutGuide.length
if (UIDevice.currentDevice().systemVersion as NSString).floatValue < 8 {
// Seems to be needed for some reason
offset -= bannerViewHeight
}
let bannerBottomConstraint = NSLayoutConstraint(item: bannerView, attribute: .Bottom, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Bottom, multiplier: 1, constant: offset + bannerViewHeight)
// self.bannerBottomConstraint = bannerBottomConstraint
bannersSuperview.addConstraint(bannerBottomConstraint)
bannersSuperview.layoutSubviews()
// bannerSuperview.setNeedsLayout()
bannersSuperview.layoutIfNeeded()
// Previously, this values was the height of the banner view, so that it starts off screen.
// Setting this to 0 and then doing an animation makes it slide in from below
bannerBottomConstraint.constant = offset
bannersSuperview.setNeedsUpdateConstraints()
UIView.animateWithDuration(animated ? 10 : 0, animations: { () -> Void in
// Calling layoutIfNeeded here will animate the layout constraint cosntant change made above
bannersSuperview.layoutIfNeeded()
})
} else {
println("Cannot show iAd when bannerView is nil")
}
}
}
func hideiAds() {
if self.showingiAd {
self.showingiAd = false
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
if let bannerView = delegate.bannerView {
if bannerView.superview == self.view {
bannerView.removeFromSuperview()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我检查我viewWillAppear:和viewDidDisappear:方法是否应该显示iAds showiAds(false)并hideiAds()根据需要调用.
无论我做什么,我似乎都无法让它发挥作用.我尝试过的其他一些事情却废弃了以下代码:
UITabBarController,然后警告UITableViewControllers显示/隐藏了iAd.修改内容/滚动指示器插入不能很好地工作,并通过UITableViewController适合导航/标签栏上方/下方的重置.viewDidLayoutSubviews,但这看起来非常昂贵?ADBannerView到内部的一些视图来使它工作UITableViewController,但它会在iOS 7上崩溃(关于tableView的一些事情必须调用super -layoutSubviews)编辑
我创建了一个UIViewController子类,用它容纳的意图UITableViewControllers通过Container View.这是我到目前为止所做的,接下来是几个问题:
class AdvertContainerViewController: UIViewController {
var tableViewController: UITableViewController?
var showingiAd = false
var bannerBottomConstraint: NSLayoutConstraint?
private var bannerTopOffset: CGFloat {
get {
var offset: CGFloat = 0
if let tabBar = self.tabBarController?.tabBar {
offset -= CGRectGetHeight(tabBar.frame)
}
if let bannerView = AppDelegate.instance.bannerView {
let bannerViewHeight = bannerView.frame.size.height
offset -= bannerViewHeight
}
return offset
}
}
override func viewDidLoad() {
super.viewDidLoad()
if self.childViewControllers.count > 0 {
if let tableViewController = self.childViewControllers[0] as? UITableViewController {
self.tableViewController = tableViewController
tableViewController.automaticallyAdjustsScrollViewInsets = false
self.navigationItem.title = tableViewController.navigationItem.title
}
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if AppDelegate.instance.shouldShowBannerView {
self.showiAds(false)
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let delegate = AppDelegate.instance
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showiAds", name: "BannerViewDidLoadAd", object: delegate)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideiAds", name: "RemoveBannerAds", object: delegate)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
if self.showingiAd {
self.hideiAds()
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
println("View did layout subviews")
if self.showingiAd {
if let bannerView = AppDelegate.instance.bannerView {
let bannerViewHeight = CGRectGetHeight(bannerView.frame)
if let bottomConstraint = self.bannerBottomConstraint {
let bannerTopOffset = self.bottomLayoutGuide.length + bannerViewHeight
if bottomConstraint.constant != bannerTopOffset {
println("Setting banner top offset to \(bannerTopOffset)")
bottomConstraint.constant = -bannerTopOffset
bannerView.superview?.setNeedsUpdateConstraints()
bannerView.superview?.updateConstraintsIfNeeded()
}
}
println("Bottom layout guide is \(self.bottomLayoutGuide.length)")
let insets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length + bannerViewHeight, 0)
self.updateTableViewInsetsIfRequired(insets)
}
}
}
private func updateTableViewInsetsIfRequired(insets: UIEdgeInsets) {
if let tableView = self.tableViewController?.tableView {
if !UIEdgeInsetsEqualToEdgeInsets(tableView.contentInset, insets) {
println("Updating content insets to \(insets.top), \(insets.bottom)")
tableView.contentInset = insets
}
if !UIEdgeInsetsEqualToEdgeInsets(tableView.scrollIndicatorInsets, insets) {
println("Updating scroll insets to \(insets.top), \(insets.bottom)")
tableView.scrollIndicatorInsets = insets
}
}
}
func showiAds() {
self.showiAds(true)
// self.showiAds(false)
}
func showiAds(animated: Bool) {
if !self.showingiAd {
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
if let bannerView = delegate.bannerView {
println("Showing iAd")
self.showingiAd = true
if (bannerView.superview != self.view) {
bannerView.removeFromSuperview()
}
let bannersSuperview = self.view.superview!
// Added the view and the left/right constraints allow for the proper height
// to be returned when bannerView.frame.size.height is called (iOS 7 fix mainly)
bannersSuperview.addSubview(bannerView)
bannersSuperview.addConstraints([
NSLayoutConstraint(item: bannerView, attribute: .Left, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Left, multiplier: 1, constant: 0),
NSLayoutConstraint(item: bannerView, attribute: .Right, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Right, multiplier: 1, constant: 0),
])
bannersSuperview.layoutIfNeeded()
let bannerBottomConstraint = NSLayoutConstraint(item: bannerView, attribute: .Top, relatedBy: .Equal, toItem: bannersSuperview, attribute: .Bottom, multiplier: 1, constant: 0)
self.bannerBottomConstraint = bannerBottomConstraint
bannersSuperview.addConstraint(bannerBottomConstraint)
bannersSuperview.layoutSubviews()
bannersSuperview.layoutIfNeeded()
let topInset = self.navigationController?.navigationBar.frame.size.height ?? 0
let insets = UIEdgeInsetsMake(topInset, 0, -self.bannerTopOffset, 0)
// Previously, this values was the height of the banner view, so that it starts off screen.
// Setting this to 0 and then doing an animation makes it slide in from below
bannerBottomConstraint.constant = self.bannerTopOffset
bannersSuperview.setNeedsUpdateConstraints()
UIView.animateWithDuration(animated ? 0.5 : 0, animations: { () -> Void in
// Calling layoutIfNeeded here will animate the layout constraint cosntant change made above
self.updateTableViewInsetsIfRequired(insets)
bannersSuperview.layoutIfNeeded()
})
} else {
println("Cannot show iAd when bannerView is nil")
}
}
}
func hideiAds() {
if self.showingiAd {
self.showingiAd = false
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
if let bannerView = delegate.bannerView {
if bannerView.superview == self.view {
bannerView.removeFromSuperview()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
迄今为止的问题:
self.view超级视图会导致旋转崩溃Auto Layout still required after sending -viewDidLayoutSubviews to the view controller. Gathered.AdvertContainerViewController's implementation needs to send -layoutSubviews to the view to invoke auto layout.应Leo Natan的要求,我已经在GitHub上创建了一个回购,我将根据我的任何尝试进行更新,并在此处解释问题.目前,问题如下:
第一个标签:
第二个标签:
最好的解决方案是使用视图控制器包含.使用视图控制器子类,它将包含广告视图和表视图控制器的视图,并将表视图控制器添加为容器视图控制器的子视图.这应该正确地处理内容插入.在容器控制器视图的每个布局上,在定位广告视图后正确定位表控制器视图层次结构.如果要隐藏广告视图,只需在容器层次结构中隐藏或删除它,并完全扩展表控制器的视图层次结构.使用层次结构时,请记住始终使用表控制器view而不是tableView直接使用表控制器.
我的答案被改编成以下GitHub回购:https: //github.com/JosephDuffy/iAdContainer
| 归档时间: |
|
| 查看次数: |
945 次 |
| 最近记录: |