     }
     
     func mergeItems(items: [Item]) {
-        //TODO: create 2 delta arrays instead of iterating over all items twice
         let existingItems = self.mutableSetValueForKey("items")
+        removeMissingItems(items, from: existingItems)
+        addNewItems(items, to: existingItems)
+    }
+    
+    func removeMissingItems(items: [Item], from existingItems: NSMutableSet) {
         for item in existingItems {
             if let managedItem: ManagedItem = item as? ManagedItem {
                 if !contains(items, managedItem.item) {

    
    deinit {
        if let box = _box {
            box.removeObserver(self, forKeyPath: "title")
            box.removeObserver(self, forKeyPath: "items")
        }
    }

}

    
    private var _box: Box?
    public lazy var box: Box = {
        let box = self.createBox()
        self.observe(box)
        self._box = box
        return box
    }()
    
    func createBox() -> Box {
        let box = Box(boxId: self.boxId(), title: self.title)
        box.items = self.associatedItems()
        
        return box
    }
    
    func associatedItems() -> [Item] {
        let managedItems = self.items.allObjects as [ManagedItem]
        return managedItems.map() { (item: ManagedItem) -> Item in
            return item.item
        }
    }
    
    func observe(box: Box) {
        box.addObserver(self, forKeyPath: "title", options: .New, context: &boxContext)
        box.addObserver(self, forKeyPath: "items", options: .New, context: &boxContext)
    }
    
    public override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        
