سؤال

انا املك UICollectionView الذي أحاول إدراج عناصر فيه ديناميكيًا/مع الرسوم المتحركة.لذلك لدي وظيفة تقوم بتنزيل الصور بشكل غير متزامن وأرغب في إدراج العناصر على دفعات.

بعد حصولي على بياناتي، أود القيام بما يلي:

[self.collectionView performBatchUpdates:^{
    for (UIImage *image in images) {
        [self.collectionView insertItemsAtIndexPaths:****]
    }
} completion:nil];

الآن بدلاً من ***, ، يجب أن أقوم بتمرير مجموعة من NSIndexPaths, ، والتي ينبغي أن تشير إلى موقع العناصر الجديدة التي سيتم إدراجها.أنا في حيرة شديدة لأنه بعد توفير الموقع، كيف يمكنني تقديم الصورة الفعلية التي يجب عرضها في هذا الموضع؟

شكرًا لك


تحديث:

resultsSize يحتوي على حجم مصفوفة مصدر البيانات، self.results, ، قبل إضافة بيانات جديدة من البيانات الموجودة في newImages.

[self.collectionView performBatchUpdates:^{

    int resultsSize = [self.results count];
    [self.results addObjectsFromArray:newImages];
    NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];

    for (int i = resultsSize; i < resultsSize + newImages.count; i++)
          [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];

          [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];

} completion:nil];
هل كانت مفيدة؟

المحلول

يرى إدراج وحذف ونقل الأقسام والعناصر من "دليل برمجة عرض المجموعة لنظام iOS":

لإدراج أو حذف أو نقل قسم أو عنصر واحد ، يجب اتباع هذه الخطوات:

  1. قم بتحديث البيانات الموجودة في كائن مصدر البيانات الخاص بك.
  2. قم باستدعاء الطريقة المناسبة لعرض المجموعة لإدراج القسم أو العنصر أو حذفه.

من الأهمية بمكان أن تقوم بتحديث مصدر البيانات الخاص بك قبل إخطار عرض المجموعة لأي تغييرات.تفترض طرق عرض المجموعة أن مصدر البيانات الخاص بك يحتوي على البيانات الصحيحة حاليًا.إذا لم يحدث ذلك ، فقد تتلقى طريقة عرض المجموعة مجموعة من العناصر الخاطئة من مصدر البيانات الخاص بك أو تطلب عناصر غير موجودة وتتعطل تطبيقك.

لذا، في حالتك، يجب عليك إضافة صورة إلى مصدر بيانات عرض المجموعة أولاً ثم الاتصال insertItemsAtIndexPaths.ستطلب طريقة عرض المجموعة بعد ذلك من وظيفة تفويض مصدر البيانات توفير طريقة العرض للعنصر المدرج.

نصائح أخرى

لقد قمت للتو بتنفيذ ذلك باستخدام Swift.لذلك أود أن أشارككم تنفيذي.قم أولاً بتهيئة مجموعة من NSBlockOperations:

    var blockOperations: [NSBlockOperation] = []

في وحدة التحكم سوف تتغير، أعد تشغيل المصفوفة:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    blockOperations.removeAll(keepCapacity: false)
}

في طريقة تغيير الكائن:

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    if type == NSFetchedResultsChangeType.Insert {
        println("Insert Object: \(newIndexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.insertItemsAtIndexPaths([newIndexPath!])
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Update {
        println("Update Object: \(indexPath)")
        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.reloadItemsAtIndexPaths([indexPath!])
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Move {
        println("Move Object: \(indexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.moveItemAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Delete {
        println("Delete Object: \(indexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.deleteItemsAtIndexPaths([indexPath!])
                }
            })
        )
    }
}

في طريقة القسم الذي تم تغييره:

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {

    if type == NSFetchedResultsChangeType.Insert {
        println("Insert Section: \(sectionIndex)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.insertSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Update {
        println("Update Section: \(sectionIndex)")
        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.reloadSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Delete {
        println("Delete Section: \(sectionIndex)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.deleteSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
}

وأخيرًا، في وحدة التحكم، تم تغيير طريقة المحتوى:

func controllerDidChangeContent(controller: NSFetchedResultsController) {        
    collectionView!.performBatchUpdates({ () -> Void in
        for operation: NSBlockOperation in self.blockOperations {
            operation.start()
        }
    }, completion: { (finished) -> Void in
        self.blockOperations.removeAll(keepCapacity: false)
    })
}

لقد أضفت شخصيًا بعض التعليمات البرمجية في طريقة deinit أيضًا، من أجل إلغاء العمليات عندما يكون ViewController على وشك إلغاء التخصيص:

deinit {
    // Cancel all block operations when VC deallocates
    for operation: NSBlockOperation in blockOperations {
        operation.cancel()
    }

    blockOperations.removeAll(keepCapacity: false)
}

كنت أواجه مشكلة مماثلة أثناء حذف العنصر من الفهرس وهذا ما أعتقد أنه يتعين علينا القيام به أثناء الاستخدام performBatchUpdates: طريقة.

1# اتصل أولاً بـdeleteItemAtIndexPath لحذف العنصر من عرض المجموعة.

2# حذف العنصر من المصفوفة.

3# تحديث عرض المجموعة عن طريق إعادة تحميل البيانات.

[self.collectionView performBatchUpdates:^{
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
            [self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
            [self.addNewDocumentArray removeObjectAtIndex:sender.tag];
        } completion:^(BOOL finished) {
            [self.collectionView reloadData];
        }];

هذا يساعدني على إزالة كافة حالات الفشل والتأكيد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top