2

Confused about a situation that might be a retain cycle?

I understand that if

class Object-A {
  var b: Object-B }

and

class Object-B {
    var a: Object-A
]

then above is horrible design because if you do

var a = Object-A()
var b = Object-B()
a.b = b
b.a = a

then this causes a retain cycle with two strong references pointing at each other.

But what if the situation is below?

class Object-A {
    var b: Object-B 
}

class Object-B {
    var randomArrayProperty: [Object-B]
}

and you try to do

var a = Object-A()
var b = Object-B()
a.b = a
b.randomArrayProperty.append(a)

Is that a retain cycle as well?

Terry Bu
  • 889
  • 1
  • 14
  • 31
  • Consider: does an array retain its contents – Wain Jun 12 '15 at 00:34
  • You might be interested in reading this article [http://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/](http://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/) – Matteo Piombo Jun 12 '15 at 03:57

2 Answers2

2

Generally speaking, with manual reference counting and automatic reference counting, reference ilands will leak. Reference cycle can be composed by more than just 2 objects.

That said I encourage you to test some code in a playground since the example in your question has some syntax and language errors.

The code below might be a starting point:

class ObjectA {
    let name: String
    var b: ObjectB

    init(name: String, b: ObjectB) {
        self.name = name
        self.b = b
    }

    deinit {
        print("\(name) deallocated")
    }
}

class ObjectB {
    let name: String
    var randomArrayProperty = [ObjectA]()

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

    deinit {
        print("\(name) deallocated")
    }
}

// Create a _possible_ leak. It depends on what we'll do next
var b: ObjectB? = ObjectB(name: "Foo B")
var a: ObjectA? = ObjectA(name: "Bar A", b: b!)
b?.randomArrayProperty.append(a!)

// No leaks
a = nil
// Remove a from array inside b, a will dealloc
b?.randomArrayProperty.removeLast()
b = nil

// Recreate a _possible_ leak.
b = ObjectB(name: "Foo1 B")
a = ObjectA(name: "Bar1 A", b: b!)
b?.randomArrayProperty.append(a!)

// Leaks
a = nil
b = nil

Then continue playing with variants ;-)

Hope this helps

Matteo Piombo
  • 6,688
  • 2
  • 25
  • 25
  • thanks for the help. it helped the most to start a new project and debug it step by step to see what was happening to those pointers. At the very end, a = nil and b=nil was not causing the deinit methods to fire (hence no print statements) and then I tried the Leaks instrument and saw a red bar appear. It's definitely a memory leak ... unless you (like you did above) properly remove a pointer from b's array property! – Terry Bu Jun 12 '15 at 20:26
0

I think so , there is a retain cycle. What instrument shows for memory leaks?

Jignesh Sheth
  • 131
  • 1
  • 2
  • 4