Swift - NSIndex forRow inSection Initializer

Posted

技术标签:

【中文标题】Swift - NSIndex forRow inSection Initializer【英文标题】: 【发布时间】:2014-10-07 15:29:43 【问题描述】:

我有以下代码:

var path = NSIndexPath(forRow: index, inSection:0);

我收到一个编译器警告:

Extra Argument 'inSection' in call

为什么?我在这里的文档中看到了初始化程序:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSIndexPath_UIKitAdditions/index.html#//apple_ref/occ/clm/NSIndexPath/indexPathForRow:inSection:

我导入了 UIKit,甚至尝试做类似的事情:

var path = UIKit.NSIndexPath(forRow: index, inSection:0);

我在这里误会了什么?

编辑:

var index = 0;

        for (key, value) in map! 
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),  (index) in
                //some code

                dispatch_async(dispatch_get_main_queue(),  (index) in
                    println("reloadRow row=" + String(index) + ",inSection:0");
                    var path = NSIndexPath(forRow: index, inSection:0);
                    self.tableView.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimation.Automatic);
                );
            );
            index++;
        

【问题讨论】:

index 是如何定义的? @MikeS 它是一个整数。 var index = 0; 等一下,让我把整个代码块贴出来,因为也许我使用闭包的方式与此有关。 @MikeS 好的,我现在有完整的代码,也许我没有正确使用闭包。 【参考方案1】:

index 可能无法被编译器识别。在 Playground 中尝试代码:

import UIKit
let index = 3
var path = NSIndexPath(forRow: index, inSection: 0)

作品

import UIKit
var path = NSIndexPath(forRow: index, inSection: 0)

错误:Extra Argument 'inSection' in call

这意味着您的index 变量定义不明确。或者您应该尝试Clean 并删除派生数据。

编辑: 删除 dispatch_async 中的 index 声明,它与您的 index 变量冲突。

dispatch_async(dispatch_get_main_queue(),  _ in
                    println("reloadRow row=" + String(index) + ",inSection:0");
                    var path = NSIndexPath(forRow: index, inSection:0);
                    self.tableView.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimation.Automatic);
                );

奖励:您应该使用带有闭包的 Swift 快捷方式。 (尾随闭包+无参数)因为它:

dispatch_async(dispatch_get_main_queue()) 
       println("reloadRow row=" + String(index) + ",inSection:0");
       var path = NSIndexPath(forRow: index, inSection:0);
       self.tableView.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimation.Automatic);
    

编辑:您在第一次异步调度中犯了同样的错误。当您声明 dispatch_async 并编写 index in 时,这与声明具有索引作为参数的函数相同。这是一个可变范围问题(您应该阅读此内容)。我更新了最终代码。

    var index = 0
    for (key, value) in map! 
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) 
            //some code
            dispatch_async(dispatch_get_main_queue()) 
                println("reloadRow row=" + String(index) + ",inSection:0");
                var path = NSIndexPath(forRow: index, inSection:0);
                self.tableView.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimation.Automatic);
            
        
        index++
    

【讨论】:

我认为你完全正确。我只是举了一个更完整的例子,它与我如何使用闭包有关吗? 所以在您的代码中,我看到您实际上在dispatch_async 中定义了另一个名为index 的变量。您不必这样做,范围内的所有变量都可以通过闭包访问。 所以这绝对修复了编译器错误。附带说明一下,当使用这样的闭包时,您知道为什么 index 的值始终是我的字典中元素的数量吗?我熟悉 javascript 闭包,它会在范围内复制变量的当前值,但 swift 似乎并非如此。 因为你在第一次异步调度中犯了同样的错误。当您声明dispatch_async 并执行 index in 时,这与声明一个以index 作为参数的函数相同。这是一个变量范围问题。我更新了最终代码。【参考方案2】:

要在异步块中保留 当前 index 值, 你应该使用Closure Expression Syntax。可以像这样立即调用。

var index = 0

for (key, value) in map! 
     (idx) in // <- this is fixed value `index`
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) 
            // some code...
            dispatch_async(dispatch_get_main_queue()) 
                var path = NSIndexPath(forRow: idx, inSection:0);
                self.tableView.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimation.Automatic);
            
        
    (index++)


OP中的代码可以翻译成JavaScript:

var index = 0;
while(...) 
  dispatch_async(GLOBAL_QUEUE, function(index)             

    //some code

    dispatch_async(MAIN_QUEUE, function(index) 
      var path = new NSIndexPath(index, 0);
      self.tableView.reloadRowsAtIndexPaths([path], ANIM_AUTO);
    );
  );

  index++;

你看到了吗?因为dispatch_async的回调不接收任何参数,所以你的innerindex将是undefined

相反,您应该编写如下代码:

var index = 0;
while(...) 
  (function(idx) 
    dispatch_async(GLOBAL_QUEUE, function()             

      //some code

      dispatch_async(MAIN_QUEUE, function() 
        var path = new NSIndexPath(idx, 0);
        self.tableView.reloadRowsAtIndexPaths([path], ANIM_AUTO);
      );
    );
  )(index++);

我认为,(function(val) ... )(val) 成语在 JavaScript 中很常见,不是吗?

【讨论】:

为什么这与我所做的不同?抱歉,我对 Swift 比较陌生,但是如果您想进行一些比较,我确实非常了解 Javascript 闭包。 我不明白为什么内部匿名函数在调用时无法访问 index 的值。 好的,我了解您现在想要表达的意思。感谢您抽出宝贵时间。 因为index“变量名”被回调函数的参数覆盖了。 感谢您对我糟糕的英语技能的耐心等待 :)【参考方案3】:

对我来说,Xcode 8.3 和 Swift 3 的工作方式如下:

  let indexPath = NSIndexPath(row: row, section: section)

【讨论】:

以上是关于Swift - NSIndex forRow inSection Initializer的主要内容,如果未能解决你的问题,请参考以下文章

一日一技:炸掉你的内存—— itertools.tee 的缺陷

swift str swumerator in swift

swift 简单的javascript repl in swift

swift [语言:Swift,语法:for-in-loop]

URL in Swift

Swift编程语言中如何实现自定义类型的for-in循环(基于Swift 2.2)