[英]How to put UITableView inside a UIView
我正在尝试在UIView中实现一个表视图。 我目前正在努力解决的一个问题是链接委托和dataSource。 如果我取消注释Xcode下面的两行,则会出现“预期声明”错误。 如果我从文档大纲中链接它们Xcode说没关系然后模拟崩溃。 如果有人能够找出问题,那就太好了。
谢谢!
import UIKit
class CurrentGameDetailView: UIView, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var theGame: GameObject? = nil
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theGame!.roundNumber
}
// tableView.delegate = self
// tableView.dataSource = self
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("OldGameDetailCell", forIndexPath: indexPath) as! OldGameDetailCell
cell.roundLabel.text = theGame!.gameRounds[indexPath.row].gamePlayed.description
...
return cell
}
}
这是震撼,完整的项目,它的工作原理。 第一个视图控制器弹出,你看到一些按钮,我只是使用带有一些随机名称的tableview,你点击名称,然后弹出另一个tableview,表格的标题与你在第一个视图上点击的单元格相同控制器。 这通过使用块来实现,UIView中没有委托,但我将所有内容放在自定义视图中,除了使用“loadView”方法创建的第一个viewcontroller视图。 如您所见,没有数据从UIView传递到UITableViewCells,您不这样做,您从第一个视图控制器的单元格中提取所有数据,并假设第一个viewcontroller的表格单元格具有TON数据形式一个JSON数组或类似的东西然后你可以通过属性声明变量将整个“得分数组”传递给下一个视图控制器,我只是告诉你如何使用UIViewController的“title”属性传递信息,你可以创建自己的属性,并在单击单元格或regualr按钮的按钮时传递整个数组。 您不希望将此信息放入Subclassed tableViewCell,但是您可以从secondViewController的cellForRowAtIndexPath传递数据来为第二页上的记分板设置自定义信息,UIVeiw可以接受UIViewController的需求,而不是相反,您使用自定义UITableView将命令发送到UIView,并且UIViewController设置自定义UITableView的数据。 这是做事的正确方法。 还有更多可以添加到这个例子来使这个超级健壮,但这个想法是这样的:
示例1: UIViewController1
button1 ==> UIViewController从网络中提取信息或告诉UIView从网络中提取此信息存储在您拥有的包含ARRAY数据的自定义UIButton中
button2 ==> UIViewController从网络中提取信息或告诉UIView从网络中提取此信息存储在您拥有的包含ARRAY数据的自定义UIButton中
button3 ==> UIViewController从网络中提取信息或告诉UIView从网络中提取此信息存储在您拥有的包含ARRAY数据的自定义UIButton中
UIViewcontroller2 UITableView将存储在上面数组中的每个按钮的数据传递给secondViewController,然后填充表,这就是它的工作原理。
示例2: UIViewController1
button1 ==> UIViewController只是向UIButton添加一个动作事件
button2 ==> UIViewController只是向UIButton添加一个动作事件
button3 ==> UIViewController只是向UIButton添加一个动作事件
UIViewcontroller2自定义方法中的TableView调用网络并根据UIViewcontroller1中按钮的标题填充数据数组,通过使用从第二个视图控制器中的viewdidload调用的自定义方法将此数组粉碎到第二个视图控制器中然后,第二个viewcontroller调用它自己的视图,该视图使用UITableView对自定义UIView子类进行了类型转换。 然后,这个UIViewController2调用“cellForRowAtIndexPath”并在单元格上用setter方法填充表,从而强制数据进入UITableView
在这两种方法中,我们在自定义视图中设置了多少个代理? ZERO,因为UIViewControllers应该负责设置数据并向下发送,UIView绝不应该向上发送数据,除非UIViewController特别要求:
工作简单的例子(程序化,没有故事板,所以你可以看到发生了什么):
AppDelegate.swift:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var rootViewController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
rootViewController = UINavigationController(rootViewController: ViewController())
if let window = window {
window.backgroundColor = UIColor.whiteColor()
window.rootViewController = rootViewController
window.makeKeyAndVisible()
}
return true
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView : UITableView?
var items = [
"Ginger",
"larry",
"Moe",
"Fred",
"Terry"]
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: CGRectMake(0, 0, 414, 736), style: UITableViewStyle.Plain)
tableView!.delegate = self
tableView!.dataSource = self
tableView!.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "Cell")
self.view .addSubview(tableView!)
}
override func loadView() {
var stuf = UIView()
stuf.frame = CGRectMake(0, 0, 414, 736)
stuf.backgroundColor = UIColor .redColor()
self.view = stuf
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat {
return 44
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomTableViewCell
cell.doWork = {
() -> Void in
self.doStuff(indexPath.row)
}
cell.labelMessage.text = items[indexPath.row] as String
return cell
}
func doStuff(integer: NSInteger) {
var newViewController = SecondViewController()
newViewController.title = items[integer] as String
var dismissButton = UIBarButtonItem(title: "done", style: UIBarButtonItemStyle.Plain, target: self, action: "dismiss")
newViewController.navigationItem.rightBarButtonItem = dismissButton
var navControl = UINavigationController(rootViewController: newViewController);
self.navigationController?.presentViewController(navControl, animated: true, completion: { () -> Void in })
}
func dismiss() {
self.navigationController?.dismissViewControllerAnimated(true, completion: { () -> Void in})
}
}
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {
var items = [
"sports score1",
"sports score2",
"sports score3",
"sports score4",
"sports score5"]
var myView: CustomViewWithTableView! {
return self.view as! CustomViewWithTableView
}
override func loadView() {
let height = self.navigationController!.navigationBar.frame.size.height as CGFloat
view = CustomViewWithTableView(frame: CGRectMake(0, height, UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.height-height as CGFloat))
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.myView.tableView.delegate = self
self.myView.tableView!.dataSource = self
self.myView.tableView!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat {
return 44
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = items[indexPath.row] as String
return cell
}
}
CustomViewWithTableView.swift
import Foundation
import UIKit
class CustomViewWithTableView: UIView {
var tableView: UITableView!
override init(frame: CGRect) {
super.init(frame: frame)
tableView = UITableView(frame: CGRectMake(frame.origin.x, frame.origin.y, frame.width, frame.height), style: .Plain)
self.addSubview(tableView)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
CustomTableViewCell.swift
import Foundation
import UIKit
class CustomTableViewCell: UITableViewCell, UIGestureRecognizerDelegate {
var labelMessage = UILabel()
var doWork: (() -> Void)?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let touchie: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "this")
touchie.delegate = self
touchie.cancelsTouchesInView = false
self.addGestureRecognizer(touchie)
labelMessage.setTranslatesAutoresizingMaskIntoConstraints(false)
contentView.addSubview(labelMessage)
//custom layout constraints
var viewsDict = ["labelMessage" : labelMessage]
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[labelMessage]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[labelMessage]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//custom touch interceptor for presentation navigation
func this () {
if let callback = self.doWork {
println("swipe detected, cell function run")
callback ()
}
}
}
正如我上面所说,位于自定义UIView中的UITableView已经死了,直到UIViewController告诉视图它没有死。 这就是MVC应该如何工作,事实上,除此之外,还有一些我个人会添加的东西,以使这一点更加明显。
1. ViewController.swift的另一个自定义UIView
2. SecondViewController.swift的另一个自定义UITableViewCell
3.第一组Button数据的对象模型,这是一个NSObject子类,这是第一个viewController屏幕上的“按钮”数据
4.另一个对象模型(可能),用于对“得分”数据中的第二组数据进行建模
5. 2个UILabel的自定义子类
6. UIButton的2个自定义子类
UIView子类在上面的5和6中声明AS属性是子类UIElements,因此5和6只控制它们自己,UIViews就像它们的直接父类一样,是UIView本身的属性。
在这个项目的最后,我会为每个ViewController提供大约5-10个带有swift和可能更多的子类(使用ObjC,它将是这个大小的两倍)。 subViews的父类只控制其子视图和属性的内容,并且永远不会控制父视图的内容,这就是IOS的设计方式,封装了从UIViewController向下延伸的“数据聊天”流而不是其他方式。
无论如何,在你的Swift冒险中好运,我也在学习Swift,因为我回答这样的问题并将强烈和高级的ObjC代码翻译成Swift。 如果您有其他问题,请询问。 谢谢,祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.