使用 didSelectRowAtIndexPath 进行转场
Posted
技术标签:
【中文标题】使用 didSelectRowAtIndexPath 进行转场【英文标题】:Segue using didSelectRowAtIndexPath 【发布时间】:2015-03-01 18:01:37 【问题描述】:我有一个核心数据项目的主从 VC 设置。如果searchBar
处于活动状态,则显示一组结果,如果未处于活动状态,则 fetchedResultsController 中的对象将显示在 MasterVC 中。
我一直在尝试使用 prepareForSegue
进行转场,但我的导师建议我使用 didSelectRowAtIndexPath
进行转场。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
var selectedNote: Note
// Check to see which table view cell was selected.
if tableView == self.tableView
selectedNote = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Note // <--this is "everything"
else
// need this to unwrap the optional
if let filteredObjects = filteredObjects
selectedNote = filteredObjects[indexPath.row]
// Set up the detail view controller to show.
let detailViewController = DetailViewController()
detailViewController.detailDescriptionLabel = selectedNote.valueForKey("noteBody") as! UILabel
// Note: Should not be necessary but current ios 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
// original code
navigationController?.pushViewController(detailViewController, animated: true)
我收到此编译器错误:
Variable 'selectedNote' used before being initialized
--在方法顶部声明!
如果我像这样在selectedNote
之前添加"self"
:
detailViewController.detailDescriptionLabel = self.selectedNote.valueForKey("noteBody") as! UILabel
'MasterViewController' does not have a member named 'selectedNote'
尽管在那里。所以我显然在搞砸一些事情。
我在let detailViewController = DetailViewController()
和lldb
之前放置了一个断点,它打印出正确的对象。我在这里四处寻找解决方案,但我做不到。我在 GitHub 上找不到适用的代码。
class Note: NSManagedObject
@NSManaged var dateCreated: NSDate
@NSManaged var dateEdited: NSDate
@NSManaged var noteTitle: String
@NSManaged var noteBody: String
任何想法如何将selectedNote
的属性转发给detailViewController
?
更新:
根据我得到的回复,我已经用这段代码关闭了编译器警告:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
var selectedNote: Note?
// Check to see which table view cell was selected.
if tableView == self.tableView
selectedNote = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Note // <--this is "everything"
else
// need this to unwrap the optional
if let filteredObjects = filteredObjects
selectedNote = filteredObjects[indexPath.row]
// Set up the detail view controller to show.
let detailViewController = DetailViewController()
detailViewController.detailDescriptionLabel.text = (selectedNote!.valueForKey("noteBody") as! String)
// Note: Should not be necessary but current iOS 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
// original code
navigationController?.pushViewController(detailViewController, animated: true)
但是当它崩溃时,我在控制台中得到了这个:
There are already notes in the app
fatal error: unexpectedly found nil while unwrapping an Optional value
但是,当我键入 po selectedObject
时,我单击的对象会显示在控制台中。
【问题讨论】:
【参考方案1】:您需要像这样将 selectedNote 声明为可选:
var selectedNote: Note?
然后在使用之前检查值是否存在。
if let note = selectedNote
// Set up the detail view controller to show.
let detailViewController = DetailViewController()
detailViewController.detailDescriptionLabel = note.valueForKey("noteBody") as! UILabel
// Note: Should not be necessary but current iOS 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
// original code
navigationController?.pushViewController(detailViewController, animated: true)
更新:
问题是您正在尝试创建 DetailViewController
let detailViewController = DetailViewController()
但是您需要的是引用 DetailViewController 以便将信息传递给它。
因此,您可以在 Interface builder 中创建从 Master 到 Detail 控制器的 segue。然后从 didSelectRowAtIndexPath
中删除逻辑 override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
// Note: Should not be necessary but current iOS 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
并在prepareForSegue方法中实现:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "showDetail"
if let cell = sender as? UITableViewCell
let indexPath = tableView.indexPathForCell(cell)!
var selectedNote: Note?
if filteredObjects?.count > 0
selectedNote = filteredObjects![indexPath.row]
else
selectedNote = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Note // <--this is "everything"
if let note = selectedNote
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = note
showDetail - 您需要在 IB 中设置的 segue 标识符。 var detailItem: AnyObject? - 你需要在 DetailViewController 中声明它。
【讨论】:
这是一个小小的进步。现在我明白了:There are already notes in the app Could not cast value of type '__NSCFString' (0x10f759c90) to 'UILabel' (0x110b1b968).
我在lldb
上做了po selectedNote
,它返回了我选择的注释,但它崩溃了
虽然这在技术上消除了编译器错误,但很有可能 selectedNote 没有被初始化,导致使用 selectedNote 时崩溃。您最好使用常规的可选... var selected注意:注意?
Adrian,看看这段代码:selectedNote.valueForKey("noteBody") as! UIL标签。你确定 selectedNote 包含 UILabel 吗?我猜它包含您想要放入 detailDescriptionLabel 的文本。在这种情况下,您需要转换为 NSString 而不是 UILabel?
这是来自DetailVC
的属性:@IBOutlet weak var detailDescriptionLabel: UILabel!
我不知道 Note 类的内部结构,但我猜你想写的内容如下:detailViewController.detailDescriptionLabel.text = note.valueForKey("noteBody") as! NSString.以上是关于使用 didSelectRowAtIndexPath 进行转场的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)