Skip to content

Weird NSObject dealloc with Swift 4 #14

Closed
AndreyZarembo opened this issue Oct 20, 2017 · 3 comments
Closed

Weird NSObject dealloc with Swift 4 #14

AndreyZarembo opened this issue Oct 20, 2017 · 3 comments

Comments

@AndreyZarembo
Copy link
Contributor

Swift 4.

Due to unknown reason NSObjects, that was used with anonymous variables in closures tend to dealloc by unknown reason.

E.g. example app:

func inject(into feedViewController: FeedViewController) {
        defineInjection(into: feedViewController) {
            $0.xkcdService = self.serviceAssembly.xkcdService
            $0.imageService = self.serviceAssembly.imageService
        }
    }

Will crash later, because feedViewController deallocated, and variables to it now works like unsafe unretained.

But this will work:

func inject(into feedViewController: FeedViewController) {
        defineInjection(into: feedViewController) { (_ feedViewController: inout FeedViewController) in
            feedViewController.xkcdService = self.serviceAssembly.xkcdService
            feedViewController.imageService = self.serviceAssembly.imageService
        }
    }

I've tried to make test, which reproduces such behaviour, but it passed normally.

@AndreyZarembo
Copy link
Contributor Author

Here's first insane solution:

    func injectObject(object: inout InjectableObject) -> Void {
        
        guard var injectableObject = object as? ObjectType else {
            
            return
        }
        
        #if swift(>=4.0)
            
            if Mirror(reflecting:object).displayStyle == Mirror.DisplayStyle.`class` {
                
                var anyObject = object as AnyObject
                var objectPTR = Unmanaged<AnyObject>.passRetained(anyObject).takeUnretainedValue() as! ObjectType
                self.injectClosure?(&objectPTR)
            }
            else {
                print("Injecting nonnobject: \(injectableObject)")
                self.injectClosure?(&injectableObject)
                object = injectableObject
            }
        #else
            self.injectClosure?(&injectableObject)
            object = injectableObject
        #endif
    }

It stops crashes. But it will make invalid references count in tests.

@AndreyZarembo
Copy link
Contributor Author

Decided to replace 'inout' closure variable with return value. This brokes API compatibility, but should fix nsobject release issue.

@AndreyZarembo
Copy link
Contributor Author

Should work in 1.4.0. Don't forget to add lots of 'return $0'

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant