Dave,这是一种更简单的方法,它没有协议,而是使用块。在您的自定义 UITableViewCell 中,我们这样做:
设置:
import Foundation
import UIKit
class EXTableViewCell: UITableViewCell {
@IBOutlet var nameLabel: UILabel!
@IBOutlet var descLabel: UILabel!
var doWork: (() -> Void)?
func swipedLeft (sender: UISwipeGestureRecognizer) {
if let callback = self.doWork {
println("swipe detected, cell function run")
callback ()
}
}
override func awakeFromNib() {
super.awakeFromNib()
let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "swipedLeft")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.addGestureRecognizer(swipeLeft)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
自定义视图控制器:
import UIKit
class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 0 //replace with the correct info
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4 //replace with the correct info
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! FFViewCell
cell.doWork = {
() -> Void in
self.doStuff(indexPath.row)
}
cell.labelMessage.text = items[indexPath.row] as String
return cell
}
func doStuff(integer: NSInteger) {
println("i got here \(integer)")
}
}
这是如何工作的:
您看,我们正在声明一个块属性,它允许我们将一个空的“函数”调用 (PER SE) 传递给您在 UIViewController 中创建的任何“EXTableViewCell”。
所以,在自定义的 UITableViewCell 中,我们声明了一个 void 块属性:
var doWork: (() -> Void)?
我们将一个触摸处理程序附加到单元格:
func swipedLeft (sender: UISwipeGestureRecognizer) {
if let callback = self.doWork {
println("swipe detected, cell function run")
callback ()
}
}
然后我们在 UIViewController 内部或主 UIViewController 中调用此处理程序,并在配置表格视图单元格时设置此属性:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! EXTableViewCell
cell.doWork = {
() -> Void in
self.doStuff()
}
return cell
}
具体来说:
cell.doWork = {
() -> Void in
self.doStuff()
}
显然,我们随后设置了“doStuff”函数来执行我们希望它在 UIViewController 中执行的操作:
func doStuff() {
println("i got here")
}
没有协议,没有混乱,没有让委托发生,所有基于块的功能。我没有用实际的 UIViewController 测试过这段代码,但是,这在 Objective-C 中可以完美运行,在发布这段代码之前,我确保它可以编译。
快速说明块的魅力,几乎所有看起来超级复杂的委托和协议都可以用块来完成,困难的部分是习惯使用块并了解它们的多功能性。可能最令人愉快的部分是您可以像使用普通属性一样使用“块属性”,但还有将处理程序事件附加到拥有块属性的对象的额外好处。无论如何,您可能还需要做一件事,但这很简单:
您可能需要像这样启动自定义表格视图单元格,使其成为 UIGestureRecognizer 的代表,如下所示:
class EXTableViewCell: UITableViewCell, UIGestureRecognizerDelegate {
您可能需要在自定义表格视图单元类中声明您的手势识别器,使其看起来像这样:
swipeLeft.delegate = self
swipeLeft.cancelsTouchesInView = false
另外,如果您在实现这一点时遇到问题,请告诉我,我会看看我是否不能完全实现它。
工作示例,经过测试并准备就绪:
自定义tableViewCell:
import Foundation
import UIKit
class FFViewCell: UITableViewCell, UIGestureRecognizerDelegate {
var labelMessage = UILabel()
var doWork: (() -> Void)?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let swipeLeft: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "this")
swipeLeft.delegate = self
swipeLeft.cancelsTouchesInView = false
self.addGestureRecognizer(swipeLeft)
labelMessage.setTranslatesAutoresizingMaskIntoConstraints(false)
contentView.addSubview(labelMessage)
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")
}
func this () {
if let callback = self.doWork {
println("swipe detected, cell function run")
callback ()
}
}
}
AppDelegate:
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
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
视图控制器:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView : UITableView?
var items = ["asdf","asdf","asdf","asdf","asdf"]
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(FFViewCell.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! FFViewCell
cell.doWork = {
() -> Void in
self.doStuff()
}
cell.labelMessage.text = items[indexPath.row] as String
return cell
}
func doStuff() {
println("i got here")
}
}
这是“滑动手势”代码,Dave:
import Foundation
import UIKit
class FFViewCell: UITableViewCell, UIGestureRecognizerDelegate {
var labelMessage = UILabel()
var doWork: (() -> Void)?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "this")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
swipeLeft.delegate = self
swipeLeft.cancelsTouchesInView = false
self.addGestureRecognizer(swipeLeft)
labelMessage.setTranslatesAutoresizingMaskIntoConstraints(false)
contentView.addSubview(labelMessage)
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")
}
func this () {
if let callback = self.doWork {
println("swipe detected, cell function run")
callback ()
}
}
}