在 moveRowAt [关闭] 之后找到 didSelectRow 的正确行

Posted

技术标签:

【中文标题】在 moveRowAt [关闭] 之后找到 didSelectRow 的正确行【英文标题】:Find the correct row for didSelectRow after moveRowAt [closed] 【发布时间】:2018-02-19 03:54:13 【问题描述】:

我有一个 TableView,其中每一行都与另一个 Storyboard 相连。 我希望用户可以根据需要对行重新排序。 但这会使其他故事板的转场崩溃。如何将“case 0: .., case 1:...”连接到最初的 indexPath.row?

到目前为止,这是我的代码的核心部分:

let languageStore = UserDefaults(suiteName: "LanguageSelect")
var languages = [String]()

func initializelanguageList() 
    if let defaults = self.languageStore?.array(forKey: "languages") as? [String] 
        self.languages = defaults
     else 
        self.languages = ["Español", "Español", "English", "English", "Deutsch", "Deutsch"]
        self.languageStore?.set(self.languages, forKey: "languages")
    

override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool 
    return true

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) 
    let language = self.languages.remove(at: sourceIndexPath.row)
    self.languages.insert(language, at: destinationIndexPath.row)
    self.languageStore?.set(self.languages, forKey: "languages")

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return languages.count

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)

    cell.textLabel?.text = self.languages[indexPath.row]
    return cell


override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
    print(indexPath.row)
    let row = indexPath.row
    switch(row)
    case 0:  
        let ViewController = UIStoryboard(name: "firstSBoard", bundle: nil).instantiateViewController(withIdentifier: "firstTabBar")
        self.navigationController?.pushViewController(ViewController, animated: false)

    case 1:            
        let ViewController = UIStoryboard(name: "secondSBoard", bundle: nil).instantiateViewController(withIdentifier: "secondTabBar")
        self.navigationController?.pushViewController(ViewController, animated: false)

   case 2:...

        break
    default: break   
         

起初我有一个带大小写开关的 TableView,它很有效。但现在我用 CanMoveRow 的可能性为我尝试了一些新的东西。这会破坏segues。我现在明白了,问题出在开关上。我必须跟踪索引。

编辑 在 Matic Oblak 的帮助下解决了:

let languageStore = UserDefaults(suiteName: "LanguageSelect")
var languages = [(name: String, index: Int)]()

override func viewDidLoad() 
    super.viewDidLoad()
        self.initializelanguageList()


func initializelanguageList() 
    if let defaults = self.languageStore?.array(forKey: "languages1.0") as? [String] 
        self.languages = defaults.enumerated().map  (name: $1, index: $0) 
     else 
        let languages = ["Español1", "Español2", "English1", "English2", "Deutsch1", "Deutsch1"]
        self.languages = languages.enumerated().map  (name: $1, index: $0) 
        self.languageStore?.set(languages, forKey: "languages1.0")
    


override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool 
    return true


override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) 
    let language = self.languages.remove(at: sourceIndexPath.row)
    self.languages.insert(language, at: destinationIndexPath.row)
    self.languageStore?.set(self.languages.map  $0.name , forKey: "languages1.0")


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return languages.count


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
         cell.textLabel?.text = self.languages[indexPath.row].name
    return cell


override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)

    switch(self.languages[indexPath.row].index)
case 0:  
    let ViewController = UIStoryboard(name: "espanol1SBoard", bundle: nil).instantiateViewController(withIdentifier: "espanol1TabBar")
    self.navigationController?.pushViewController(ViewController, animated: false)

case 1:            
    let ViewController = UIStoryboard(name: "espanol2SBoard", bundle: nil).instantiateViewController(withIdentifier: "espanol2TabBar")
    self.navigationController?.pushViewController(ViewController, animated: false)

 case 2:...

    




【问题讨论】:

单元格中显示的数据与您需要显示的情节提要有什么联系? 我不得不削减我的代码。现在我可以补充一些,希望你能理解。我只是希望用户可以重新排序语言,但重新排序后 segues 无法正常工作。 不,你还没有回答我的问题。您构建了一个动态的语言列表,但您似乎有一个硬编码的故事板列表。为什么? 那是因为在将对象插入新目标之前,您还没有从源中删除对象。由于 cellForRowAt 方法没有足够的行数来显示,因此应用程序不可避免地会崩溃。 @rmaddy 到目前为止它运行良好,现在我想使用 CanMoveRow 的可能性,我必须学习新的东西。但到目前为止,在我的搜索中,我找不到可行的解决方案。 【参考方案1】:

我认为您留下了代码的一些重要部分,这些部分是造成您所遇到的混乱的原因。例如,为什么你会在didSelectRowAt 中有一个 switch 语句?它应该如下所示:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
    let ViewController = UIStoryboard(name: "firstSBoard", bundle: nil).instantiateViewController(withIdentifier: "firstTabBar")
    ViewController.language = languages[indexPath.row]
    self.navigationController?.pushViewController(ViewController, animated: false)

正如您在这种情况下所看到的,您的数组是唯一的事实来源,并且顺序永远不会影响您的结果。

但如果您确实需要跟踪这些索引,您只需将结构更改为以下内容:

var languages = [(name: String, index: Int)]()

然后

self.languages = defaults.enumerated.map  (name: $1, index: $0) 

cell.textLabel?.text = self.languages[indexPath.row].name

switch(self.languages[indexPath.row].index)
    case 0:  

编辑:将完整代码添加到地图语言:

func initializelanguageList() 
    if let defaults = self.languageStore?.array(forKey: "languages") as? [String] 
        self.languages = defaults.enumerated.map  (name: $1, index: $0) 
     else 
        let languages = ["Español", "Español", "English", "English", "Deutsch", "Deutsch"]
        self.languages = languages.enumerated.map  (name: $1, index: $0) 
        self.languageStore?.set(languages, forKey: "languages")
    

或者,如果在任何情况下您需要将它们转换回来,您会这样做:

self.languageStore?.set(self.languages.map  $0.name , forKey: "languages")

【讨论】:

是的,我想我必须跟踪索引!所以我在顶部放了一个 let name = ["Español", ...] ,但是我应该在 func initializelanguageList() 的 else ... 中做什么? @LarsB 请检查编辑 谢谢!但是对于枚举部分我得到了错误:“方法'枚举'被用作属性;添加()来调用它”所以我必须放入()模拟器以这个配置开始,我可以使用segues。但是当我重新排序单元格时,模拟器崩溃并出现错误:尝试将非属性列表对象(...)设置为关键语言的 NSUserDefaults/CFPreferences 值 @LarsB 您很可能仍在直接调用self.languages 而不是映射它。请检查我写的最后一行。 非常感谢!有用。我想现在我明白了。但是还有一件小事:当我更改语言名称时,我必须先删除应用程序才能看到更改。当我在未来的版本中更改名称时,用户在通过 App Store 获得更新后会遇到同样的问题吗?

以上是关于在 moveRowAt [关闭] 之后找到 didSelectRow 的正确行的主要内容,如果未能解决你的问题,请参考以下文章

将两个表中的值插入第三个表[关闭]

Flutter项目删除了相关的dart文件之后运行flutter run或者 F5编译运行时会报这个错误.... were declared as an inputs, but did not exi

tomcat启动总是会有一个警告警告: did not find a matching property.

The 'brew link' step did not complete successfully

Android 12 apk Installation did not succeed

Android 12 apk Installation did not succeed