【问题标题】:swift splitview controller default cellswift splitview 控制器默认单元格
【发布时间】:2015-06-30 08:30:38
【问题描述】:

我目前正在开发一个在 xcode6 中使用 swift 的带有拆分视图控制器的项目。

我目前拥有它,以便在应用加载时记住您之前选择的单元格,并将“选择”该单元格。 However when the cell is selected it doesn't initiate the segue to the detail view controller loading that cells related information.

这是我的主视图控制器代码,想知道我可以添加什么来在应用加载时为所选单元格启动 segue?

class MasterViewController: UITableViewController {

var detailViewController: DetailViewController? = nil
var titles = [String]()
var ageGroups = [String]()
var danceForms = [String]()
var danceDivisions = [String]()
var danceCategories = [String]()
var routineIds = [Int]()



override func awakeFromNib() {
    super.awakeFromNib()
    self.clearsSelectionOnViewWillAppear = false
    self.preferredContentSize = CGSize(width: 320.0, height: 600.0)
}

override func viewDidLoad() {
    super.viewDidLoad()
   self.navigationItem.setRightBarButtonItems([rightAddBarButtonItem,rightSearchBarButtonItem], animated: true)





    let query = PFQuery(className: "Schedule")
    query.orderByAscending("routineId")
    query.whereKey("eventId", equalTo: 16)
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in

        if let objects = objects {


            for object in objects {

                self.titles.append(object["title"] as! String)
                self.ageGroups.append(object["ageGroup"] as! String)
                self.danceForms.append(object["danceForm"] as! String)
                self.danceDivisions.append(object["danceDivision"] as! String)
                self.danceCategories.append(object["danceCategory"] as! String)
                self.routineIds.append(object["routineId"] as! Int)



                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    self.tableView.reloadData()
                    var returnValue: Int? = NSUserDefaults.standardUserDefaults().objectForKey("selectedCell") as? Int
                    if let value = returnValue{

                    }
                    else{
                        returnValue = 1;
                    }
                    if  returnValue! > self.routineIds.count{
                        returnValue = 1;
                    }
                    let rowToSelect:NSIndexPath = NSIndexPath(forRow: returnValue!-1, inSection: 0);  //slecting 0th row with 0th section
                    self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None);

                })




            }


        }
    }







}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


// MARK: - Segues


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "showDetail" {
        if let indexPath = self.tableView.indexPathForSelectedRow() {
            let object = routineIds[indexPath.row] as Int
            let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
            controller.detailItem = object
            controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
            controller.navigationItem.leftItemsSupplementBackButton = true
        }
    }
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return titles.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("scheduleCell", forIndexPath: indexPath) as! scheduleCell

    var myCustomSelectionColorView = UIView()
    myCustomSelectionColorView.backgroundColor = UIColor.whiteColor()
    cell.selectedBackgroundView = myCustomSelectionColorView



    cell.routineId.text = "\(routineIds[indexPath.row])"
    cell.routineTitle.text = titles[indexPath.row]
    cell.routineAgeGroup.text = " - \(ageGroups[indexPath.row])"
    cell.routineDanceForm.text = " - \(danceForms[indexPath.row])"
    cell.routineDivision.text = danceDivisions[indexPath.row]
    cell.routineCategory.text = danceCategories[indexPath.row]

    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.

    return false
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    println(routineIds[indexPath.row])
    NSUserDefaults.standardUserDefaults().setInteger(routineIds[indexPath.row], forKey: "selectedCell")
    NSUserDefaults.standardUserDefaults().synchronize()
    var returnValue: Int? = NSUserDefaults.standardUserDefaults().objectForKey("selectedCell") as? Int
    if returnValue! == 1{

    }

    println(returnValue)

}

【问题讨论】:

    标签: swift ipad ios8 uisplitviewcontroller


    【解决方案1】:

    您可以使用 UIViewController 上的 performSegueWithIdentifier 方法手动启动 segue。

    // in your dispatch_async block:
    self.performSegueWithIdentifier("showDetail", self)
    

    【讨论】:

    • 谢谢,这似乎是在启动 segue,并传递数据,但我现在又遇到了另一个错误...如果我尝试打印一个通过 println(object["title"] as! String) 传递的值,它可以工作...但是如果我尝试将相同的值直接分配给标签作为文本:self.rITitle.text = (object["title"] as! String) 它失败说“致命错误:在展开可选值时意外发现 nil”为什么该值可以用于 println 但会失败分配给标签?
    • 如果您尝试在 performSegue 方法中访问目标视图控制器中的视图,它们可能为 nil。您可能需要向目标视图控制器添加一个实例变量,其中包含您要在其上显示的所有数据。我建议将您的标题数组、年龄组数组等重构为具有标题、年龄组等的某个 DanceGroup 类型的单个数组,然后将 DanceGroup 的实例传递给您的详细视图控制器。在 viewDidLoad 中,检查该变量并使用它填充视图(如果它不为 nil)。
    • 想通了,因为我的 dispatch_async 在 for 循环中,我必须检查所选索引是否 == 当前循环索引,以便它只会尝试将正确的数据传递给detailView 而不是传递多行 nil 和一个正确的行...感谢您的帮助
    【解决方案2】:

    另一种方法是利用state restoration。好处是应用程序可以恢复每个视图控制器的状态,而无需您编写或处理您现在正在执行的大部分操作。

    状态恢复将为您保存和加载应用程序状态,让您不必在NSUserDefaults 中保留详细信息,例如选择了哪个单元格。 SDK实际上保留了很多有用的细节,比如你的splitViewController是折叠还是展开,导航栏是紧凑还是隐藏等等。这些都是不错的选择,使用状态时免费获得恢复。

    要利用状态恢复,您应该:

    1. 让您的AppDelegate 实现application:shouldSaveApplicationState:application:shouldRestoreApplicationState:

    2. 为您要保留的每个视图控制器分配恢复标识符。您可以在 Storyboard 中轻松做到这一点。

    3. application:willFinishLaunchingWithOptions: 显示您应用的窗口。

    4. 使用encodeRestorableStateWithCoder:decodeRestorableStateWithCoder:对视图控制器的状态进行编码和解码

    另一个好处是视图控制器可以保存自己的关于它正在显示的对象的详细信息,而另一个视图控制器不需要执行任何 segue(或传递任何详细信息)。它允许您的视图控制器更加独立,并且与其他视图控制器的耦合度更低。

    状态恢复确实减少了您必须编写的代码量,从长远来看,这是有回报的,必须维护、支持和升级应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多