iOS-怒怼面试官:百行代码高仿抖音(Tik Tok)

首先说一下:大家应该都知道现在面试官太装逼了。我认识一位从360出来的人说:一个alloc你都要让我转成rutime.再成c函数,然后栈空间,叶子函数再去问汇编,太屎了。

前阵子面试的时候也是如此,后来再问到一些苹果官方提供的一些控件时却居然一点都不知道。

比如有一个面试官问:一个业务上要求左右滑动时切换页面,怎么做?

我的回答是:左右滑动的模块有几个就写几个基于UIViewController的类,然后这些模块由一个UIPageViewController去控制。

我说了各种各样的好处之后,面试官还不以为意,说我用一个UIScrollView去控制不行吗?设置他的frame就行了。

我曾经在这篇文章说过时至今日使用frame的缺点太突出了,我个人不建议。另一方面,如此多的代码写在一个VC当中,那么业务代码耦合的就太厉害了。而且我也在这篇文章里说过苹果在UIKit里出来一个Container的概念。

之后面试官又问:如果我要是在之后的需求当中再加上上下滑动呢?类似抖音那种。

我的回答便是:使用UIPageViewController更容易实现。效果如下:

代码运行之后的效果图1

代码运行之后的效果图2

鉴于Xcode自带的"Debug view Hierarchy"不太好用,大家凑合着看这个效果。

抖音的效果是:视频列表页可以上下滑动以切换视频源,同时视频列表往右滑动则到搜索页,往左侧滑动则到up主的用户详情页。

接下来我就说说我的思路(以Swift语言来实现)。
第一步:创建一个新工程,默认rootVC是工程中的ViewController

第二步:基于UIViewController分别创建三个VC,为SearchViewController(搜索页),VideosViewController(视频列表页)和UserInfoViewController(up主的用户信息页)。如下图:

第三步:在ViewController里创建UIPageViewController,并且实现切换三个模块。代码如下:

override func viewDidLoad() {
        super.viewDidLoad()
        
        // 创建搜索页,视频列表页和用户详情页
        let searchVC : SearchViewController = SearchViewController()
        let videosVC : VideosViewController = VideosViewController()
        let userInfoVC : UserInfoViewController = UserInfoViewController()
        self.viewControllers = [searchVC, videosVC, userInfoVC]
        
        // 创建UIPageViewController
        let pageVC : UIPageViewController = UIPageViewController.init(transitionStyle: UIPageViewController.TransitionStyle.scroll, navigationOrientation: UIPageViewController.NavigationOrientation.horizontal, options: nil)
        pageVC.setViewControllers([videosVC], direction: UIPageViewController.NavigationDirection.forward, animated: false, completion: nil)
        pageVC.dataSource = self
        pageVC.delegate = self
        
        // 将pageVC添加到当前VC
        self.addChild(pageVC)
        self.view.addSubview(pageVC.view)
        pageVC.view.frame = self.view.bounds
        pageVC.didMove(toParent: self)
    }
    // UIPageViewController必须的两个代理方法,这两个代理方法控制三个页面的先后顺序
 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        
        var index : Int = self.viewControllers.index(of: viewController) ?? NSNotFound
        if (index == 0) || (index == NSNotFound) {
            return nil
        }
        
        index -= 1
        
        return self.viewControllers[index]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        var index : Int = self.viewControllers.index(of: viewController) ?? NSNotFound
        if (index == 0) || (index == NSNotFound) {
            return nil
        }
        
        index += 1
        if index >= self.viewControllers.count {
            return nil
        }
        
        return self.viewControllers[index]
    }

经过以上三步就简单的实现了三个页面的左右切换。那么视频列表的上下切换也是基于UIPageViewController的,步骤如下:
第四步:基于UIViewController创建一个VideoViewController,这个类用来播放视频

第五步:在VideosViewController(视频列表页)里创建UIPageViewController,实现上下滑动,而且是无限滑动。跟第三步类似,但是参数设置不一样。代码如下:

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.view.backgroundColor = UIColor.blue
        
        // 当前类的功能描述
        let desLabel : UILabel = UILabel(frame: self.view.bounds)
        desLabel.numberOfLines = 0
        desLabel.textColor = UIColor.white
        desLabel.textAlignment = NSTextAlignment.center
        desLabel.text = "抖音视频列表页\n往右滑到搜索页,往左滑到用户详情页\n上下滑切换视频"
        self.view.addSubview(desLabel)
        
        // 创建 UIPageViewController
        let pageVC : UIPageViewController = UIPageViewController.init(transitionStyle: UIPageViewController.TransitionStyle.scroll, navigationOrientation: UIPageViewController.NavigationOrientation.vertical, options: nil)
        let videoVC : VideoViewController = VideoViewController()
        videoVC.videoIndex = self.currentIndex
        pageVC.setViewControllers([videoVC], direction: UIPageViewController.NavigationDirection.forward, animated: false, completion: nil)
        pageVC.dataSource = self
        pageVC.delegate = self
        
        // 将pageVC添加到当前VC
        self.addChild(pageVC)
        self.view.addSubview(pageVC.view)
        pageVC.view.frame = self.view.bounds
        pageVC.didMove(toParent: self)
    }
    
    // MARK: - UIPageViewControllerDataSource
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if self.currentIndex == 1 {
            return nil;
        }
        
        let videoVC : VideoViewController = VideoViewController()
        videoVC.videoIndex = self.currentIndex - 1
        videoVC.view.backgroundColor = UIColor.white
        return videoVC;
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let videoVC : VideoViewController = VideoViewController()
        videoVC.videoIndex = self.currentIndex + 1
        videoVC.view.backgroundColor = UIColor.white
        return videoVC;
    }

    // MARK: - UIPageViewControllerDelegate
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        // 简单的动画效果
        let videoController : VideoViewController = pageViewController.viewControllers?[0] as! VideoViewController
        self.currentIndex = videoController.videoIndex!
        UIView.animate(withDuration: 2.0) {
            videoController.view.backgroundColor = UIColor.clear
        }
    }

效果图如下:

仿抖音效果

此工程我已上传到Github,你的star是我的动力。

最后打个广告,个人第三方库:
UDUserDefaultsModel:NSUserDefaults的改进方案
YIIFMDB:直接操作Model进行增删改查,数学运算等,且sql语句易于管理

你可能感兴趣的:(iOS-怒怼面试官:百行代码高仿抖音(Tik Tok))