2016-06-07 1 views
0

В моем приложении загружаю загрузку JSON.Обновление свойства в структуре внутри массива

Затем я сохраняю это как массив структур и использую это для заполнения UITableView.

Одним из свойств структуры является изображение NSURL. Еще одно свойство - необязательно UIImage.

Структура имеет мутирующую функцию downloadImage, которая использует URL-адрес, чтобы загрузить изображение и сохранить его в своей собственности.

Как это ...

struct SearchItem { 
    // other properties... 
    let iconURL: NSURL 
    var icon: UIImage? 

    mutating func downloadImage() -> Task<UIImage> { 
     let tsc = TaskCompletionSource<UIImage>() 

     NSURLSession.sharedSession().downloadTaskWithURL(iconURL) { 
      (location, response, error) in 
      if let location = location, 
       data = NSData(contentsOfURL: location), 
       image = UIImage(data: data) { 
       self.icon = image 
       tsc.setResult(image) 
       return 
      } 

      tsc.setError(NSError(domain: "", code: 1, userInfo: nil)) 
     }.resume() 

     return tsc.task 
    } 
} 

Проблема у меня это. (и я был в тупике от этого в прошлом).

У меня есть массив [SearchItem], который я использую для заполнения таблицы.

В cellForRow У меня есть код ... if let searchItem = items[indexPath.row]...

Затем он проверяет, является ли образ ноль и загрузка ...

if let image = searchItem.icon { 
    cell.imageView.image = image 
} else { 
    searchItem.downloadImage().continueOnSuccessWith(Executor.MainThread) { 
     _ in 
     tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None) 
    } 
} 

Но это никогда не проходит, чтобы поместить изображение в ячейку , Это связано с тем, что SearchItem является структурой и поэтому pass-by-value. Таким образом, элемент поиска, который я загружаю для изображения, не является тем же SearchItem, что и тот, который хранится в массиве.

Как я могу гарантировать, что загруженное изображение затем сохраняется в SearchItem внутри фактического массива?

+1

Простые: использование классов: D – jrturton

+1

@jrturton но но ...Разве это не идеальный вариант использования для структур? – Fogmeister

+1

, очевидно, нет, в противном случае это было бы работать – jrturton

ответ

4

Использование классов.

Вы получаете копию searchItem в своем методе cellForRow. Что бы вы ни делали с этим, это будет сделано только для этой копии. То, что вы на самом деле хотите, это изменения, внесенные вами в эту копию для применения к версии в массиве.

Поэтому вам нужна эталонная семантика, поэтому используйте классы.

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

+0

Кажется, вы правы. «Строй, я разочарован». Как побочный вопрос/комментарий, чем больше я пишу Swift, тем больше бесполезных структур. Есть ли какой-либо прецедент для них, который не страдает от таких же проблем, как это? Честно говоря, чем больше я пишу Swift, тем больше мне это не нравится и думаю, что я могу вернуться к Objective-C. :( – Fogmeister

+0

Вы можете просто обновить структуру в массиве до «новой» структуры (после мутации) – Alexander

+0

@AMomchilov Вот что я говорю в последней строке ответа – jrturton

3

Структуры представляют собой легкие объекты данных, которые не передаются по ссылке, а вместо этого копируют себя по мере необходимости, когда вы: а) передаете ее новой функции, б) попытайтесь получить доступ к ней в блоке. Массивы в Swift также работают несколько иначе, чем их коллеги Obj-C. Когда у вас есть объект класса Array, массив будет ссылочным типом, и вы сможете достичь того, чего вы пытаетесь достичь здесь. Но, с другой стороны, если Array имеет структуру Struct, массив теряет свою ссылочную семантику и вместо этого использует copy-by-value.

Эта разница действительно эффективна при правильном использовании, вы можете значительно оптимизировать свой код, сделать его быстрее, иметь меньше ошибок, создаваемых изменяемыми объектными ссылками, имеющими изменения в разных частях кода и т. Д. Но это зависит от вас как разработчик, чтобы увидеть, где выгоды этих оптимизаций полезны или где имеет смысл использовать объекты вместо этого.

+0

Спасибо. Проблема заключается в том, что любые онлайн-ссылки, которые нетривиальны, по-видимому, не согласуются с хотя бы одной ссылкой. Пытаться следовать им приводит к таким случаям. экземпляр, в отдельной статье говорится о том, чтобы использовать структуры для 'Person Data'. Но тогда, если вам нужно изменить имя этого человека, вы будете менять копию оригинала, поэтому кажется, что это неправильное использование для структуры. не могут использовать их для использования за пределами тривиальных входных параметров. Но тогда я мог бы использовать кортеж для чего-то подобного! Хотел бы хороший веб-сайт, если вы можете порекомендовать его? Thans – Fogmeister

+3

I c рекомендуем эти два видеообъявления WWDC 2015 Apple dev: https://developer.apple.com/videos/play/wwdc2015/414/ - https://developer.apple.com/videos/play/wwdc2015/408/ –

+3

@Fogmeister Преимущество типов значений заключается в том, что они позволяют безопасную мутацию. Всякий раз, когда вы вызываете библиотечный метод и проходите в своей структуре, вы можете быть уверены, что ваша структура не будет затронута и что никаких неожиданных побочных эффектов не произойдет. Кроме того, этот минимизированный обмен означает, что вам не нужно беспокоиться о синхронизации в многопоточных приложениях. – Alexander

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