先把Main Interface哪里去掉,因为将不会用到storyboard
首先在AppDelegate里手动添加tableViewController
import UIKit
import CoreData
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let controller = MyTableViewController()
let navigationController = UINavigationController(rootViewController: controller)
window?.rootViewController = navigationController
return true
}
在来是创建一个TableViewController
import UIKit
class MyTableViewController: UITableViewController {
var viewModel: ViewModelProtocol?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "My TableView"
tableView.register(MyCell.self, forCellReuseIdentifier: "cell")
self.tableView.rowHeight = 100
let updateCallBack: ()-> Void = {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
viewModel = ViewModel(updateCallBack: updateCallBack)
viewModel?.loadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel?.getObject().count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
cell.getConfigure(viewModelLoadImage: viewModel?.getViewModelLoadImage(index: indexPath.row))
return cell
}
}
我之前有一篇有介绍如何下载图片和用cell创建的function getConfigure进行封装还有如何用MVVM下面是链接
https://blog.youkuaiyun.com/SwiftIOS_watsUp/article/details/101006775
再来是建tableView里的cell
import Foundation
import UIKit
class MyCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUp()
}
let typeLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont.boldSystemFont(ofSize: 20)
return label
}()
let imageViewFashion: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.clipsToBounds = true
return imageView
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setUp() {
addSubview(typeLabel)
self.contentView.addSubview(imageViewFashion)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[v0]-16-[v1(100)]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": typeLabel, "v1": imageViewFashion]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": typeLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": imageViewFashion]))
}
func getConfigure(viewModelLoadImage: ViewModelLoadImage?) {
typeLabel.text = viewModelLoadImage?.getType()
viewModelLoadImage?.getImage { (image) in
DispatchQueue.main.async {
self.imageViewFashion.image = image
}
}
}
}
需要注意的是每次创建一个新的自定义控件都需要加
label.translatesAutoresizingMaskIntoConstraints = false
因为每个控件的default是它会自动把根据它的constrain进行resize,所以需要把它等于false才不会影响到现在的tableViewCell
func setUp() {
addSubview(typeLabel)
self.contentView.addSubview(imageViewFashion)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[v0]-16-[v1(100)]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": typeLabel, "v1": imageViewFashion]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": typeLabel]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: ["v0": imageViewFashion]))
}
在手动创建tableViewCell的时候,最麻烦的是每个控件的constraints,这里我用的withVisualFormat这个关键字,这个方法比较容易视觉上清楚一些,这里的H是horizontal,就是从横向的方式,第一个控件v0,我设置的typeLabel,里最左边的距离的16,在往左16是另一个控件v1,imageViewFashion。然后我们还需要给每个控件给它纵向的constrain
最后是效果图
github:
https://github.com/grm121616/MVVMBuildCellProgrammatically