#ios #swift #performance #core-data #uicollectionview
#iOS #swift #Производительность #core-data #uicollectionview
Вопрос:
Итак, я создаю приложение для обмена сообщениями, используя JSQMessagesViewController. Я связал его с fetchedResultsController, который отслеживает каждый раз, когда я вставляю новый объект в контекст. В didPressSend я вставляю в контекст:
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
let message = NSEntityDescription.insertNewObject(forEntityName: "Message", into: context) as! Message
message.text = text
message.timestamp = Date() as NSDate?
}
Поэтому каждый раз, когда я вставляю новый объект в контекст с помощью DidPressSend (кнопка отправки), запускается контроллер полученных результатов
var InsertOperation = [BlockOperation]()
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
if type == .insert {
InsertOperation.append(BlockOperation(block: { [weak self] in
self?.collectionView.collectionViewLayout.invalidateLayout()
self?.collectionView.insertItems(at: [newIndexPath!])
DispatchQueue.main.async {
self?.scrollToBottom(animated: true)
}
}))
}
}
Затем операция блокировки выполняется в didChangeContent
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
collectionView.performBatchUpdates({
for operation in self.InsertOperation {
operation.start()
self.InsertOperation.removeFirst()
}
})
}
Это, наконец, вставляет элемент в представление коллекции, которое было создано в didPressSend. Сначала он вставляет их с феноменальной скоростью. Все работает потрясающе!. Однако, когда я добираюсь до 100 или около того элементов в CollectionView, он начинает становиться все более и более вялым. У меня нет ничего необычного в моих методах делегирования CollectionView. Просто то, что требуется как таковое:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
let msg : Message = fetchedResultsControler.object(at: indexPath) as! Message
let messageData = JSQMessage(senderId: senderId, displayName: senderDisplayName, text: msg.text)
return messageData
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (fetchedResultsControler.sections?[0].numberOfObjects)!
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
return cell
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
let bubbleFactory = JSQMessagesBubbleImageFactory()
return bubbleFactory?.outgoingMessagesBubbleImage(with: .black)
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
return nil
}
Я не включил это в код, но когда пользователь нажимает кнопку «Назад» и возвращается в чат, он разбивает чат на страницы, показывая только последние 20 сообщений, что снова делает его сверхбыстрым. Однако очень возможно, что пользователь может отправить много сообщений, прежде чем нажать «Назад» и предоставить просмотру коллекции возможность разбиения на страницы. В результате пользовательский опыт серьезно ухудшится, поскольку пользователь находится в чате. Я заметил, что в таких приложениях, как tinder (я тестировал это), вы можете отправлять 1000 сообщений одновременно, и ничто не замедлится. Должен быть трюк, который я не могу разгадать.
Спасибо!
Комментарии:
1.почему вы
invalidate
collectionView's
размещаете каждый раз, когда отправляете сообщение?2. Привет, Адил, я убрал это, так как только что понял, что на самом деле мне это вообще не нужно. Однако это не решает проблему производительности.