Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EXC_BAD_ACCESS when extending CLPlacemark -- variable accessed outside definition scope

I have an issue that I've figured out how to fix but I want to understand why it doesn't work -- because it makes no sense to me. Here's a minimal example that demonstrates my issue:

import XCTest
import CoreLocation

class ExampleTests: XCTestCase {

    var okay: ext!

    // this test works fine
    func testOkay(){
        okay = ext()
        XCTAssertNotNil(okay)
    }

    // this test crashes with EXC_BAD_ACCESS(code=1, address=0x10)
    func testNotOkay(){
        let notOkay: ext
        notOkay = ext()
        XCTAssertNotNil(notOkay)
    }
}

extension ExampleTests {
    class ext : CLPlacemark{

    }
}

I'm following a book to develop a simple TodoList application that uses CoreLocation to geocode addresses. As part of testing, I had to create a mock CLPlacemark object to test the geocoding functionality.

In the book, I was told I had to declare a variable for this mock as a property of the Test class because otherwise "the test would crash since the place mark is accessed outside of its definition scope."

This can be seen in the example above. testOkay() works fine because okay was declared as a class property. testNotOkay() crashes with an EXC_BAD_ACCESS error, because I've tried to instantiate a new instance of ext within the function.

Now, if I do not extend CLPlacemark, the problem goes away -- i.e. I can declare variables of type ext in a function or as a property of the class with no issues.

What is going on here? I see no reason why the second example should crash while the first one works. In my actual code, it seems frivolous to declare my mock placemark instances as class properties when they're only used in one or two functions. There must be something I don't understand about Swift that is causing this problem.

Thanks!!

like image 990
Ted Yavuzkurt Avatar asked Feb 06 '23 12:02

Ted Yavuzkurt


1 Answers

I recently run into this issue when testing feature which required providing predefined CLPlacemark instances as an input. After some research I found that someone had similar problem with CLBeacon class.

EXC_BAD_ACCESS when setting a CLBeacon to nil

Placemark objects are typically generated by a CLGeocoder object, although you can also create them explicitly yourself.

Despite Apple documentation saying that you can create CLPlacemark instances by yourself. This class is not a nice guy when it comes to subclassing. It depends on a private class called CLPlacemarkInternal which is nil when you create an instance. On the image below you can see how this object looks in debugger. The _internal ivar has value of 0x0 which is nil.

screenshot

Crash with EXC_BAD_ACCESS message occurs when the object you instantiated gets deallocated. Regardless whether you go out of scope or assign another object (or nil) to the variable. Why is it happening? This is a question to Apple developers. But below you can find some workarounds other people implemented.

  • http://szulctomasz.com/2015/07/01/ios-unit-testing-in-swift-and-clplacemark-mocking.html
  • Extending CLPlacemark results in EXC BAD ACCESS
like image 173
Kamil Szostakowski Avatar answered Feb 26 '23 05:02

Kamil Szostakowski