4
votes

I have the following code:

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

and I get a compiler warning saying:

Extra Argument 'inSection' in call

Why? I see the initializer in the documentation here:

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

I imported UIKit, and even tried doing something like:

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

What am I misunderstanding here?

EDIT:

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++;
        }
3
How is index defined? - Mike S
@MikeS its an integer. var index = 0; Hold on, let me post the whole code block, because maybe the way I am using closures has something to do with this. - thatidiotguy
@MikeS Okay, I have the full code now, perhaps I am not using closures correctly. - thatidiotguy

3 Answers

8
votes

index may not be recognized by the compiler. Try the code in playground:

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

Works

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

Error: Extra Argument 'inSection' in call

It means that your index variable is not well defined. Or you should try to Clean and delete the derived data.

Edit: Remove the index declaration in your dispatch_async it conflicts with your index variable.

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);
                });

Bonus: You should use Swift nice shortcuts with closures. (trailing closure + no parameters) as it:

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);
    }

Edit: you do the same mistake in the first dispatch async. When you declare a dispatch_async and you write { index in it's the same thing as declaring a function with an index as a parameter. It's a variable scope issue (you should read about this). I update the final code.

    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++
    }
2
votes

To preserve the current index value in async blocks, you should use Closure Expression Syntax. It can be called immediately like this.

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++)
}

The code in OP can be translated to 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++;
}

You see? Because dispatch_async's callback doesn't receive any arguments, so your inner index will be undefined.

Instead, you should code like this:

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++);
}

I think, (function(val){ ... })(val) idiom is very common in JavaScript, isn't it?

1
votes

For me Xcode 8.3 and Swift 3 works like below:

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