27

The Leak is a Root Leak, In this image is being caused several times on the same line, but there is another below that is called single time and also produces a leak.

enter image description here

This is the call stack after calling the line of code stated before.

enter image description here

This is the class where the leak is located by Instruments:

class Item {
 var id: String!
 var name: String!

 internal init(name: String) {
    self.name = name
    self.id = name
 }

 var description: String {
    return "(\(id)) \(name)"
 }
}

Leak is detected at line of computed variable description containing return "(\(id)) \(name)" and it gets solved after changing description into:

var description: String {
    return "(" + id + ") " + name
}

Update:

or

var description: String {
    if let id = self.id as? String, let name = self.name as? String {
        return "(\(id)) \(name)"
    }
    return "NO AVAILABLE DESCRIPTION"
}

The last one emits a "Conditional cast from 'String!' to String always succeeds".

So, even this looks like a hack.

Why is this causing a leak?

Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
  • It is likely something outside this class that is causing the leak. Check the class that creates this Item object. Is it referencing id or name? Also, is the leak a "cycle? This also would indicate that something outside this class is holding a reference to it. – Stephen May 04 '15 at 20:39
  • @Stephen I have updated the question, adding some insight of the leak – Hugo Alonso May 04 '15 at 21:39
  • Both forms of the string concatenation should be valid. It looks like this could be an Apple bug. You could try filing a bug report with Apple. – Stephen May 05 '15 at 13:22

1 Answers1

13

I tested your code and gone through few threads and my understanding is that you have to optional binding if let clause, when using string interpolation instead of using optional variables directly. For String concatenation, if we use optionals directly there is no problem. The problem is with interpolation.

var description: String {
    if let id = self.id, let name = self.name {
        return "(\(id)) \(name)"
    }
    return "NO AVAILABLE DESCRIPTION"
}

You may get more info here memory leak in Swift String interpolation. Seems like a bug and may be in future release it will be solved.

Community
  • 1
  • 1
Amit89
  • 3,000
  • 1
  • 19
  • 27
  • This memory leak, incase of interpolation is happening for me if i am using more than one optional variable, with one it works good. – Amit89 May 09 '15 at 05:15
  • I tried your code, and even when my class' variables `id` and `name` are `String!` and Xcode states that "Conditional cast from 'String!' to String always succeeds" it compiles and stopped throwing such a leak. – Hugo Alonso May 11 '15 at 14:55
  • I tested here, i am also getting same thing. – Amit89 May 11 '15 at 15:06
  • 1
    I added your hint into main question for better visibility, if no one can give me a better answer of exactly **"Why?"** this is happening then the correct answer will be assigned to you. As I will assume that there is a bug, sadly I can't submit such a bug report myself. – Hugo Alonso May 11 '15 at 15:14
  • 1
    Here is a bug report for a similar problem at [bugs.swift.org](https://bugs.swift.org/browse/SR-1728) if you want to check its status. – user2067021 Aug 29 '16 at 00:55