利用自定义window实现点击状态栏使当前的tableView滚动到顶部

  • 最近在用Xcode7做项目的过程中遇到了如题的需求,按照iOS8以前的做法程序就直接崩溃了。可以看出这个需求从Xcode6到Xcode7的实现方法上有了一些改动,但是基本思路还是没有变,利用自定义UIWindow来实现。状态栏本质上是一个UIWindowLevelStatusBar级别的UIWindow,它之所以能够一直显示在APP的顶端不被覆盖,就是因为其优先级比我们的keyWindow高,这里为了监听到状态栏的点击,就自定义一个和状态栏尺寸一样大的window覆盖在上面就OK了,下面看代码。
  • 在程序启动完成后就创建一个状态栏大小的窗口放在导航栏上
 /**
     初始化顶部窗口,并设置其跟控制器,注意Xcode7以后窗口不设置跟控制器就报错
     */
    private func setupTopWindow()
    {
        topWindow = UIWindow(frame:UIApplication.sharedApplication().statusBarFrame)
        topWindow?.windowLevel = UIWindowLevelAlert
        topWindow?.backgroundColor = UIColor.clearColor()
        topWindow?.rootViewController = TopWindowViewController()
        topWindow?.backgroundColor = UIColor.blueColor()
        topWindow?.hidden = false
    }

注意:Xcode7和Xcode6的区别就在这里,Xcode6创建窗口不一定需要根控制器,就给一个警告,Xcode7以后不给跟控制器就直接崩溃了,那就来一个更控制器专门用来做这个窗口的点击,在touchBegan中实现自己的代码即可,下面看下我实现的小demo
- 首先,在keyWindow的根控制器为一个导航控制器,导航控制器的跟控制器为SuperViewController

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        window = UIWindow(frame: UIScreen.mainScreen().bounds)
        //设置keyWindow的跟控制器
        window?.rootViewController = UINavigationController(rootViewController: SuperViewController())
        //初始化顶部窗口
        setupTopWindow()
        window?.makeKeyAndVisible()
        return true
    }

在SuperViewController的view上放了一个尺寸和控制器View一样大的scrollView

view.addSubview(scorollView)
scorollView.frame = UIScreen.mainScreen().bounds

在scrollview上添加两个TableView

//加入子控制器
        addChildViewController(firstTableViewController)
        addChildViewController(secondTableViewController)
        //加入控制器对应的view
        scorollView.addSubview(firstTableViewController.view)
        firstTableViewController.view.frame = UIScreen.mainScreen().bounds
        scorollView.addSubview(secondTableViewController.view)
        secondTableViewController.view.frame = CGRectMake(UIScreen.mainScreen().bounds.size.width, 0, UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height)

这样就大概两个TableView就可以通过scrollview来回滚动了,那么怎么判断一个view当前是否可见呢,有以下几个条件,重点是一个坐标系的转换

func isVisiable() ->Bool
    {
        if alpha <= 0.01 || hidden == true
        {
            return false
        }
        let convertRect = superview!.convertRect(frame, toView: UIApplication.sharedApplication().keyWindow)
        
        let rectIntersectsRect = CGRectIntersectsRect(convertRect,UIApplication.sharedApplication().keyWindow!.bounds)
        
        if rectIntersectsRect && self.window == UIApplication.sharedApplication().keyWindow
        {
            return true
        }
        else
        {
            return false
        }
    }

然后再给UIView写一个分类寻找当前可见的tableView,然后利用递归的思想去寻找当前显示在用户面前的那个“MRright”

    func searchVisiableView()
    {
        for view in subviews
        {
            if !(view.isVisiable() && view.isKindOfClass(UITableView.self))
            {
                for childView in view.subviews
                {
                    childView.searchVisiableView()
                }
            }
            else
            {
                (view as! UITableView).scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: true)
                return
            }
        }
    }

详细的demo地址:https://github.com/xuhongru/xuhongru_Priest/tree/master

你可能感兴趣的:(利用自定义window实现点击状态栏使当前的tableView滚动到顶部)