2015-07-11 2 views
1

У меня есть пользовательский UITableView, который заботится о анимации для переупорядочения ячеек и отлично работает со стандартным тестовым массивом, который не использует основные данные.Использование «didMoveCellFromIndexPathToIndexPathBlock» с основными данными

При попытке приложения, которое использует данные ядра с двумя объектами «Папка» и «Элемент» с отношениями To Many, я получаю сообщение об ошибке.

[(п)] не имеет элемент, называемый exchangeObjectAtIndex

для;

tableView.didMoveCellFromIndexPathToIndexPathBlock = {(fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) -> Void in 

let delegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 
let context: NSManagedObjectContext = delegate.managedObjectContext! 

self.itemsArray.exchangeObjectAtIndex(toIndexPath.row, withObjectAtIndex: fromIndexPath.row) 

    var error: NSError? = nil 
    if !context.save(&error) { abort() } 

} 

Это потому, что:

Классов NSSet, NSMutableSet и NSCountedSet объявить программный интерфейс на неупорядоченные коллекции объектов.

Поэтому я попытался преобразовать NSSet в NSMutableArray для управления порядком объектов.

func itemsMutableArray() -> NSMutableArray { 
    return NSMutableArray(array: (item.allObjects as! [Item]).sorted{ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending }) 
} 

Но затем я получаю следующее сообщение об ошибке в моем табло; это связано с тем, что изменчивый массив равен AnyObject, поэтому быстрый не считает, что он имеет свойство title.

cell.textLabel? .text = folderMutableArray [indexPath.row] .title

Итак я иду туда, где я начал. Я просто пытаюсь создать простой список и упорядочить порядок объектов.

Вот мой Folder Класс:

class Folder: NSManagedObject { 

@NSManaged var date: NSDate 
@NSManaged var title: String 
@NSManaged var item: NSSet 

/// Method 1 - Converting to a NSMutableArray 

// func itemsMutableArray() -> NSMutableArray { 
// return NSMutableArray(array: (item.allObjects as! [Item]).sorted{ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending }) 
// } 


// Method 2 - creating an array of type Item 
func itemArray() -> [Item] { 
    let sortByDate = NSSortDescriptor(key: "Date", ascending: true) 
    return item.sortedArrayUsingDescriptors([sortByDate]) as! [Item] 
} 
} 

производительность приложения делают это все время, так что я знаю, что это возможно, но не знает, как, Кто-нибудь знает, где я неправильно или есть какие-либо идеи или предложения?

ответ

4

Этого очень легко достичь. Вам необходимо добавить свойство index на ваш Item. Установите его в целочисленный тип, и всякий раз, когда вы добавляете новый Item, установите это значение в индекс, под которым вы хотите, чтобы элемент отображался. Это свойство должно быть добавлено как в Core Data Model, так и в вашем классе Item как NSManaged.

Далее вам нужно добавить переходное свойство к вашему классу Folder под названием arrayOfItems (вы можете переименовать его, конечно, в любое удобное для вас). В Core Data Model установите значение Transient и Transformable.

В вашем Folder классе необходимо выполнить следующие действия:

class Folder: NSManagedObject { 

    @NSManaged var date: NSDate 
    @NSManaged var title: String 
    @NSManaged var item: NSSet 
    @NSManaged var arrayOfItems: [Items] 

    override func awakeFromFetch() { 
     super.awakeFromFetch() 
     self.regenerateItems() 
    } 

    func regenerateItems() { 
     let desc = NSSortDescriptor(key: "index", ascending: true) 
     if let array = item.sortedArrayUsingDescriptors([desc]) as? [Item] { 
      self.arrayOfItems = array 
     } 
    } 

} 

Теперь, когда вы запрашиваете любой экземпляр Folder вы получите правильный отсортированный и изменяемый массив Item с. Вам нужно рассмотреть только два других случая.

И это связано с тем, что awakeFromFetch вызывается только при получении данных из Core Data. Итак, вы должны рассмотреть другие сценарии.

Добавление нового Item

При добавлении нового Item вам необходимо либо вручную добавить новый Item к arrayOfItems или вам нужно позвонить regenerateItems(), как только вы закончите добавление нового Item. Например, предположим, что где-то в вашем коде вы создаете исходные данные:

var folder = NSEntityDescription.insertNewObjectForEntityForName("Folder", inManagedObjectContext: self.managedObjectContext!) as! Folder 
var firstItem = NSEntityDescription.insertNewObjectForEntityForName("Item", inManagedObjectContext: self.managedObjectContext!) as! Item 
// assuming that you have an inverse relationship from Item to Folder 
// line below will assign it and will add your firstItem to Folder's 
// NSSet of items 
firstItem.folder = folder 

// at this point your firstItem is added to your Folder but 
// arrayOfItems is empty. So, you should call 
folder.arrayOfItems = [firstItem] 
// or you can call folder.regenerateItems() 

Код выше относится к ситуации, когда вы создаете свои первоначальные данные. Если где-то в вашем коде вы добавляете новый Item в папку, которая уже имеет некоторые Items вы следующее:

var newItem = NSEntityDescription.insertNewObjectForEntityForName("Item", inManagedObjectContext: self.managedObjectContext!) as! Item 
// assuming that you have an inverse relationship from Item to Folder 
// line below will assign it and will add your newItem to Folder's 
// NSSet of items 
newItem.folder = someExistingFolder 

// at this point your newItem is added to your Folder but 
// arrayOfItems is not yep updated and does not include newItem 
// so you should either call 
folder.arrayOfItems.append(newItem) 
// or you can call folder.regenerateItems() 

Перегруппировка Items

Кроме того, при перемещении Item с в вашем представлении таблицы вам нужно будет изменить их индекс и порядок в arrayOfItems. Самый простой способ добиться этого, вероятно, будет изменить порядок элементов в arrayOfItems, а затем перебрать этот массив, присваивающей правильные новые индексы для всех элементов в нем:

func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) { 
    let itemThatMoved = currentFolder.arrayOfItems[sourceIndexPath.row] 
    currentFolder.arrayOfItems.removeAtIndex(sourceIndexPath.row) 
    currentFolder.arrayOfItems.insert(itemThatMoved, atIndex:destinationIndexPath.row) 
    var currentIndex = 0 
    for item in currentFolder.arrayOfItems { 
     item.index=currentIndex 
     currentIndex++ 
    } 
} 

Позвольте мне знать, если это помогает или если у вас есть другие вопросы.

P.S. Я настоятельно рекомендую вам изменить название вашего отношения с item до items. Плюсное имя items гораздо логичнее для NSSet.

+0

Большое вам спасибо за этот ответ, действительно информативный. Проделал некоторые рефакторинг кода и обновил модель Core Data и классы, как вы предложили. Я понимаю обновления до сих пор, но не знаю, что вы имеете в виду при добавлении элемента в папку. Почему мне нужно добавлять к arrayOfItems, когда это создает массив элементов? или почему мне нужно вызвать 'rebateItems()' после? Причина, по которой я прошу, - это полностью понять код, а не слепо обновлять код, надеясь на результат. Я обновил свой вопрос с помощью кода, чтобы добавить элемент. – RileyDev

+0

Дайте пару минут. Я расскажу об этом в своем ответе. –

+0

Я собираюсь принять этот ответ, большое вам спасибо за вашу помощь. Я действительно ценю это! Очень информативно. Все еще работая над ошибкой, которая, когда я перемещаю ячейку, другие ячейки меняют свои имена на ячейку, которую они заменяют. Например. если их 5 ячеек - 1,2,3,4,5, а I - 3 в конце, где 5 должно быть вместо 1,2,4,5,3, другие ячейки обновляют свой текст на заменяющую ячейку, например. 1,2,3 (4), 4 (5), 3 (перемещенная ячейка) – RileyDev

Смежные вопросы