Fix Memory Leaks

This commit is contained in:
Robert Payne 2016-11-24 00:03:41 +13:00
parent ddf15594fd
commit eb107818ac
5 changed files with 55 additions and 28 deletions

View File

@ -27,7 +27,8 @@
import AppKit
#endif
public class Constraint {
@objc(SnapKitConstraint)
public final class Constraint : NSObject {
internal let sourceLocation: (String, UInt)
internal let label: String?
@ -67,6 +68,7 @@ public class Constraint {
self.constant = constant
self.priority = priority
self.layoutConstraints = []
super.init()
// get attributes
let layoutFromAttributes = self.from.attributes.layoutAttributes
@ -260,7 +262,7 @@ public class Constraint {
}
for layoutConstraint in layoutConstraints {
let existingLayoutConstraint = existingLayoutConstraints.first { $0.canUpdate(constraint: layoutConstraint) }
let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint }
guard let updateLayoutConstraint = existingLayoutConstraint else {
fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)")
}

View File

@ -45,7 +45,7 @@ public class ConstraintDescription {
let sourceLocation = self.sourceLocation else {
return nil
}
let from = ConstraintItem(target: self.item as AnyObject, attributes: self.attributes)
let from = ConstraintItem(target: self.item, attributes: self.attributes)
return Constraint(
from: from,

View File

@ -28,7 +28,7 @@
#endif
public class ConstraintItem : Equatable {
public final class ConstraintItem {
internal weak var target: AnyObject?
internal let attributes: ConstraintAttributes

View File

@ -160,20 +160,42 @@ public class ConstraintMaker {
internal static func prepareConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
let maker = ConstraintMaker(item: item)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
var constraints: [Constraint] = []
for description in maker.descriptions {
guard let constraint = description.constraint else {
continue
}
constraints.append(constraint)
}
return constraints
}
internal static func makeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
let maker = ConstraintMaker(item: item)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
var constraints: [Constraint] = []
for description in maker.descriptions {
guard let relation = description.relation,
let related = description.related,
let sourceLocation = description.sourceLocation else {
continue
}
let from = ConstraintItem(target: description.item, attributes: description.attributes)
let constraint = Constraint(
from: from,
to: related,
relation: relation,
sourceLocation: sourceLocation,
label: description.label,
multiplier: description.multiplier,
constant: description.constant,
priority: description.priority
)
constraints.append(constraint)
}
for constraint in constraints {
constraint.activateIfNeeded(updatingExisting: false)
}
@ -192,10 +214,13 @@ public class ConstraintMaker {
let maker = ConstraintMaker(item: item)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
var constraints: [Constraint] = []
for description in maker.descriptions {
guard let constraint = description.constraint else {
continue
}
constraints.append(constraint)
}
for constraint in constraints {
constraint.activateIfNeeded(updatingExisting: true)
}

View File

@ -59,33 +59,33 @@ extension LayoutConstraintItem {
return nil
}
internal var constraints: [Constraint] {
return self.constraintsHashTable.allObjects
return self.constraintsSet.allObjects as! [Constraint]
}
internal func add(constraints: [Constraint]) {
let hashTable = self.constraintsHashTable
let constraintsSet = NSMutableSet()
for constraint in constraints {
hashTable.add(constraint)
constraintsSet.add(constraint)
}
}
internal func remove(constraints: [Constraint]) {
let hashTable = self.constraintsHashTable
let constraintsSet = NSMutableSet()
for constraint in constraints {
hashTable.remove(constraint)
constraintsSet.remove(constraint)
}
}
private var constraintsHashTable: NSHashTable<Constraint> {
let constraints: NSHashTable<Constraint>
private var constraintsSet: NSMutableSet {
let constraintsSet: NSMutableSet
if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSHashTable<Constraint> {
constraints = existing
if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSMutableSet {
constraintsSet = existing
} else {
constraints = NSHashTable<Constraint>()
objc_setAssociatedObject(self, &constraintsKey, constraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
constraintsSet = NSMutableSet()
objc_setAssociatedObject(self, &constraintsKey, constraintsSet, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return constraints
return constraintsSet
}