我试图在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
}
}
答案 0 :(得分:9)
这里是震撼,完整的项目,它的工作原理。第一个视图控制器弹出,你看到一些按钮,我只是使用带有一些随机名称的tableview,你点击名称,然后弹出另一个tableview,表格的标题与你在第一个视图上点击的单元格相同控制器。这可以通过在UIView中使用块而不是委托来实现,但是我将所有内容放在自定义视图中,除了使用" loadView"创建的第一个viewcontroller视图。方法。正如您所看到的,没有数据从UIView传递到UITableViewCells,您不这样做,您从第一个视图控制器的单元格中提取所有数据并假设第一个视图控制器&#39 ; s表格单元格有一个TON数据形成一个JSON数组或类似的东西然后你可以传递整个"得分数组"通过属性声明变量到下一个视图控制器,我只是告诉你如何使用"标题"传递信息。 UIViewController的属性,您可以创建自己的属性,并在单击单元格或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子类,这是&#34;按钮&#34;第一个viewController屏幕上的数据
<强> 4。另一个对象模型(可能)来模拟&#34;得分中的第二组数据&#34;数据强>
<强> 5。 2个UILabel的自定义子类
<强> 6。 2个UIButton的自定义子类
UIView子类在上面的5和6中声明子类UIElements的AS属性,所以5和6只控制它们自己,UIViews就像它们的直接父类一样,是UIView本身的属性。
在这个项目的最后,我会为每个ViewController提供大约5-10个带有swift和可能更多的子类(使用ObjC,它将是这个大小的两倍)。 subViews的父类只控制其子视图和属性的内容,并且永远不会控制父视图的内容,这就是IOS的设计方式,使用&#34;数据聊天的流程进行封装。从UIViewController向下延伸而不是相反。
无论如何,在你的Swift冒险中祝你好运,我也在学习Swift,因为我回答这样的问题,并将强烈和高级的ObjC代码翻译成Swift。如果您有其他问题,请询问。谢谢,祝你好运!