Swift 3 enums leak memory when the class contains an array

I found a memory leak in Swift. It gave me nightmares because my code was full of small leaks everywhere, and then I managed to reduce it to this small example,

import UIKit

enum LeakingEnum {
    case
    LeakCase,
    AnotherLeakCase
}

class Primitive {
    var lightingType: LeakingEnum = .LeakCase
    var mysub : [Int] = []
    init() {
        mysub.append(80)
    }
}

class ViewController: UIViewController {
    var prim: Primitive?
    override func viewDidLoad() {
        super.viewDidLoad()
        prim = Primitive()
    }
}

If you run this program on an iPhone and Profile with Instruments, you’ll find this leak in Array._copyToNewBuffer,

  • implement login screen before swrevealcontroller
  • Playing prepared animation in iOS
  • Xcode CI and cocoapods private repo
  • Use default back button in navigation controller
  • Using core plot for iPhone, drawing date on x axis
  • Cannot convert value of type (PFUser!, NSError) void to expected argument type PFUserResultBlock
  • Memory leak detected with Instruments

    If I remove the call to mysub.append, it stops leaking. If I remove the enum from Primitive, it stops leaking as well. All the classes where I have an enum leak like this. What’s going on with Swift enums?

    Reproduced in Swift 3, Xcode 8.2.1, and iOS 10.2, on both an iPhone6 and an iPad Pro. Can’t reproduce in the Simulator, or in a device with iOS 9.3.2.
    You can download a minimal sample app here: https://github.com/endavid/SwiftLeaks

    Is this a known bug? Is there any work around?

    Edit:

    Because this remind me of another enum bug, Accessor gives the wrong value in Swift 1.2/2.0 Release build only, I tried making the enum an @objc Int enum, but it still leaks. However, making lightingType directly an Int does fix the leak…

    Edit2:
    After updating my iPhone to 10.3 and Xcode to 8.3, the leak is gone. It seems it was an issue of iOS 10.2…

    Solutions Collect From Internet About “Swift 3 enums leak memory when the class contains an array”

    Hey @endavid managed to replicate the issue consistently. We spend a good time trying to figure out what was going on and your post helped a lot!

    Here is the sample repo: https://github.com/Giphy/ios-memory-leak-sample

    Radar: https://openradar.appspot.com/radar?id=4992108083544064

    We are developing SDKs and same exact issue surfaced with a small difference. Since we wanted things to interop we added @objc to the enum definition and things started to leak exactly the way you described given your class has two properties, one enum and one mutable array.

    Consistently reproduced the leak:

    // Without @objc this enum won't leak
    // however when this enum is included in a class
    // which contains an array, it will leak
    @objc enum leakingObjCMarkedEnum: Int {
    
        // Just some random cases.
        case apple, orange
    }
    
    // Wrapper class which contains an enum and Array
    // The class needs to contain the the Array in order for
    // the Enum to leak.
    class WrapperClass {
    
      // Optional enums marked with @objc will leak.
      var leakyOptionalEnum: leakingObjCMarkedEnum?
    
      // Include an array to trigger this behaviour.
      // Empty arrays won't cause the leak, so lets add an arbitrary Int
      var myArray: [Int] = [80]
    }
    
    class ViewController: UIViewController {
    
      // Hang on to a reference to our Wrapper Class instance.
      var wc: WrapperClass?
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        // Allocate an instance of our class
        // and things will start leaking at this point.
        wc = WrapperClass()
      }
    }
    

    Work Around:

    If we convert the optional enum class property to a non-optional, leak will disappear.

    // Let's convert the optional property to a non-optional
    var leakyOptionalEnum: leakingObjCMarkedEnum = .orange
    

    Edit:

    It is fixed by guys @ Apple:
    https://bugs.swift.org/browse/SR-5625
    PR: https://github.com/apple/swift/pull/11341