0

I Wrote a function that return two Strings, when calling the function regularly its works fine, but when I'm running the function through loop, I'm getting this error:

Thread 1: EXC_BAD_ACCESS (code=2, address=0xbfffcba0)

override func viewDidLoad()
{
    super.viewDidLoad()
    test()
}

func test()
{
    var funcs = [checkButton]
    var a = checkButton(value: 1) // Runs OK
    for f in funcs{
        var result = f(value: 1) // Fail
    }
}

func checkButton(#value: Int) -> (location: String, pattern: String){
    return ("abc","cba")
}

Update:

I'm using Xcode 6 beta 2, and running Mavericks on VMware Workstation.

Also, I've just created new clean project with that code and still getting the error.

5
  • 3
    there is no problem with this code at all. runs like a charm on my computer. Commented Jun 19, 2014 at 15:44
  • How can it be? I'm running Xcode version 6.0 (6A215I), same as you? Commented Jun 19, 2014 at 15:49
  • mine is Xcode 6.0 (6A216f), briefly the beta-2. you are using the beta-1. Commented Jun 19, 2014 at 15:50
  • So I've updated the Xcode, and still getting the same error with different address: 0xbfffcbb0. Commented Jun 19, 2014 at 16:57
  • It works fine for me on beta 1 (6A215l) Commented Jun 19, 2014 at 16:57

2 Answers 2

1

This code runs fine for me. Your EXC_BAD_ACCESS must be coming from some other part of your code. Try setting a breakpoint and stepping through the code to find the line throwing the error.

From the “The Swift Programming Language.”

“An instance method can be called only on a specific instance of the type it belongs to. It cannot be called in isolation without an existing instance.”

checkButton() is an instance method, not a closure. It works in the first case because there is an implicit self. before checkButton(). It will not work in the second case.

If you want to make checkButton a closure you could declare it like so:

let checkButton = { (#value: Int) -> (location: String, pattern: String) in
    return ("abc","cba")
}
Sign up to request clarification or add additional context in comments.

4 Comments

When skipping this line its works fine. I have tried it many times, re-write that again and again, but nothing, still getting the error.
Can you edit your question to display the whole file and your call to the test() method?
So how can it be that its working fine for everyone but me? And also, how can I make it work? Thanks.
It was working fine for us because you only gave the test and checkButton methods without their context. I'm not sure what your end goal is but I'll update my answer again with a way to make it work.
0

I can confirm that it doesn't work for me either. Created a iOS single-view app from template, and added above code. crash. As an experiment, I took it out of the array (just f = self.checkButton) and got the same result.

I think it's a bug in the compiler.

First according to the book, a method is actually a function which is actually a closure, albeit one with special properties and restrictions. Shouldn't self.checkButton (or implicit version) be sufficient to "give it an existing instance", making it a closure? If MattL is correct that instance methods can't be used as closures, then the compiler shouldn't allow you to assign one to anything.

Second, the crash occurs on the exit, not on the call. And if you reference self in checkButton, (e.g. println(self.title) having previously set title), it works fine. That suggests that the instance is indeed known and operating, just something wrong on the return.

Third, changing it to a class method doesn't help. Changing these lines

  var a = ViewController.checkButton(value: 1) 
  var funcs = [ViewController.checkButton]

  class func checkButton(#value: Int) -> (location: String, pattern: String)

results in the same crash. I don't see any similar prohibition on context for class methods.

Fourth, if you simply change the return type from (location: String, pattern: String) to just String and return abc, then the whole thing works fine.

Fourth, if you wrap test and checkButton in a new class testClass, and then call it as below, it works:

    class testClass {

    func test()
    {
        var funcs = [checkButton]
        var a = checkButton(value: 1) // Runs OK
        for f in funcs {
            var result = f(value: 1) // Fail
            println(result)
        }
    }

    func checkButton(#value: Int) -> (location: String, pattern: String){
        return ("abc","cba")
    }

}


class ViewController: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()
        let g = testClass()
        g.test()
    }


}

Now change testClass to testClass: NSObject and it crashes.

So it looks like the compiler is botching up a method return when called as a closure with a tuple in a Obj-C subclass. When I put it like that, I must say that it's not terribly surprising nobody's noticed yet; you're really pushing the edge here!


More practically, in the meantime, if it's helpful, an alternative to changing your method to a closure is to keep it unchanged and just wrap it as you put it in the array:

 var funcs = [{value in self.checkButton(value: value)}]

This seems to work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.