UIStackView的基於功能組織程式碼拆分的一些猜想

weixin_34290000發表於2018-05-23

所有的最初,都來源於偉大的理想,和一時發熱的頭腦。想法不一定對,但卻是一個方向,希望各位小夥伴一起探討,相互交流,能指點一二,不勝感激。

比心


2419271-8182d624fcc3df61.jpg
?.jpg

首先說一下UIStackView是個什麼東西

UIStackView看字面意思,就是在UIView中插入了一個Stack, Stack是什麼意思了,查下字典,“堆疊,排列”, 沒錯,UIStackView就是用來排列其它子View的容器,而且這個排列是線性的,什麼意思?也就是說要麼橫向排列,要麼縱向排列,你不能橫縱交替,但是我們可以進行巢狀的使用來達到一些縱橫交替的效果。

UIStackView使用屬性和方法說明

//構造方法,views為需要排列到StackView中的子Views  
public init(arrangedSubviewsviews: [UIView])  
  
//返回StackView中裝入的Views  
public var arrangedSubviews:[UIView] { get }  
  
//往StackView中裝入一個View  
public func addArrangedSubview(view: UIView)  
  
//從StackView中移除一個View  
public func removeArrangedSubview(view: UIView)  
  
//插入一個View到指定的Index  
public func insertArrangedSubview(view: UIView, atIndexstackIndex: Int)  
  
//設定排列方向,橫向還是縱向,預設是橫向  
public var axis: UILayoutConstraintAxis  
  
//屬性決定了其管理的檢視在沿著其軸向上的佈局  
public var distribution: UIStackViewDistribution  
  
//(對齊)屬性決定了其管理的檢視在垂直於其軸向上的佈局;比如Center居中對齊, Fill,填滿, Leading,起點對齊等。  
public var alignment: UIStackViewAlignment  
  
 //設定每個View間的間距,如果是橫向排列的話,就是橫向間距,縱向的話,就是縱向間距。  
public var spacing: CGFloat  
  
public var baselineRelativeArrangement: Bool  
public var layoutMarginsRelativeArrangement: Bool  

猜想

  • 首先我們要針對我們的場景,對於我們的一些控制器裡可能會涵蓋很多的功能模組點,比如說在首頁的展示中我們會有 Banner輪播圖,Icon圖示表,最新內容展示區,最熱內容展示區,視訊功能區,音訊功能區,列表功能區等等。諸如此類的功能量,都放到我們的一個控制器中,可想而知我的程式碼量以及耦合度。不論是前期開發還是後期維護都是非常不便。今天我們猜想一下一個可行的解決方案,當然也是會有別的解決方案的,這次只是介紹這個與UIStackView相關的一個解決方案的猜想。
我們把每個功能點的組織程式碼分別拆分到單獨的子控制器當中,把業務分散,只把控制權放在當前主題介面。

UIStackView如何結合UIScrollView使用?

對於介面,滑動功能一般是必不可少的。
UIStackView沒有自帶scrollView的,那就只能用自已結合ScrollView來實現了。好吧,其實實現也很簡單,首先建立一個scrollView,然後把stackView放到scrollView中去就可以了,當然要使其滑動,需要正確設定scrollView的contentSize,描述就是這樣的。
上程式碼:


import UIKit

class ViewController: UIViewController {

    var scrollView: UIScrollView?
    var stackView: UIStackView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor  = UIColor.white
        setUI()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        scrollView?.contentSize = CGSize(width: (stackView?.frame.width)!, height: (stackView?.frame.height)!)
        print(scrollView?.contentSize.height ?? 0)
    }
    
}

extension ViewController {
    
    fileprivate func setUI() {
        scrollView = UIScrollView()
        view.addSubview(scrollView!)
        scrollView?.snp.makeConstraints({ (make) in
            make.edges.equalTo(self.view)
        })
        // 重新整理
        scrollView?.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(ViewController.loadData))
        scrollView?.mj_footer = MJRefreshBackFooter(refreshingTarget: self, refreshingAction: #selector(ViewController.loadMoreData))
        
        stackView = UIStackView()
        stackView?.axis = .vertical
        stackView?.spacing = 10
        scrollView?.addSubview(stackView!)
        stackView?.snp.makeConstraints({ (make) in
            make.top.equalTo(self.scrollView!)
            make.left.equalTo(self.scrollView!)
            make.right.equalTo(self.scrollView!)
            make.width.equalTo(self.scrollView!)
            make.bottom.equalTo(self.scrollView!)
        })
        
        setChildVC()
    }
    
    // 控制器
    fileprivate func setChildVC() {
        addVC(BannerVC())
        addVC(NewIconVC())
        addVC(AudioVC())
        addVC(VideoVC())
        addVC(ListVC())
    }
    // 載入控制器
    fileprivate func addVC(_ vc: HomeBaseVC) {
        self.addChildViewController(vc)
        self.stackView!.addArrangedSubview(vc.view)//將vc.view放於stackView容器中,此後不需要設定vc.view的任何約束,就能實現從上到下排列顯示,寬高都是自適應大小,注意這兒必須要用addArrangedSubview而不能用addSubView

        vc.homeDelegate = self
    }
    
    // 模擬重新整理
    @objc fileprivate func loadData() {
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 2) {
            DispatchQueue.main.async {
                self.scrollView?.mj_header.endRefreshing()
                //清空stackView中的 subView
                if let arrangedSubviews = self.stackView?.arrangedSubviews {
                    for subView in arrangedSubviews {
                        self.stackView?.removeArrangedSubview(subView)
                    }
                }
                // 刪除子控制器
                for childVC in self.childViewControllers {
                    childVC.removeFromParentViewController()
                }
                
                // 重新載入
                self.setChildVC()
                
            }
        }
    }
    // 模擬載入更多
    @objc fileprivate func loadMoreData() {
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 2) {
            DispatchQueue.main.async {
                self.scrollView?.mj_footer.endRefreshing()
                self.scrollView?.mj_footer.endRefreshingWithNoMoreData()
                self.addVC(ListVC())
            }
        }
    }
}

extension ViewController: UPdataContainsDelegate {
    // 根據控制器回撥設定約束高度
    func upDataContains( _ childVC: HomeBaseVC, _ containHeight: CGFloat) {
        // childVC.view.frame = CGRect(x: 0, y: 0, width: kSCREEN_WIDTH, height: 200) //不用設FRAME了,設了也不會起作用的,因為stackView會自動去新增一些約束。
        childVC.view.snp.makeConstraints { (make) in
            make.height.equalTo(containHeight)
        }
    }

}

實現當中我覺得是有很多不合理的地方,希望各位小夥伴們有好的方法方案,一定要點撥一二哦。☺ 加油共勉。

Demo的連線: https://gitee.com/MrBigCat/BCUIStackViewIdea

相關文章