Каков наилучший (проектный) способ передачи NSArray объектов модели в объект представления? - PullRequest
3 голосов
/ 27 августа 2010

У меня есть класс модели BankAccount, который содержит такие данные, как номер счета, название банка, транзакции и т. Д. Каждый из этих транзакций является экземпляром класса Transaction и содержится в транзакциях NSArray.

У меня также есть BankAccountView, который отображает все это в одном представлении. Прямо сейчас я передаю все данные в виде отдельных переменных (т.е. bankAccountView.accountNumber = bankAccount.accountNumber, bankAccountView.bankName = bankAccount.bankName).

Проблема / дилемма возникает, когда мне нужно передать транзакции в представление. Я научился разделять классы модели и представления, поэтому я предполагаю, что нехорошо просто передавать массив транзакций BankAccount в BankAccountView, поскольку этот массив содержит экземпляры класса модели Transaction.

Итак, что я делаю сейчас, так это: я беру каждый экземпляр транзакции, транслирую его в NSDictionary, затем устанавливаю bankAccountView.transactions в NSArray, содержащий эти словари. Это работает, и я чувствую, что это держит мою модель и классы представления отдельно, но это также кажется слишком сложным, как будто я пишу много кода для чего-то, что может быть намного проще.

Есть ли лучший способ сделать это? Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 27 августа 2010

Я думаю, вы уже зашли слишком далеко и должны передать весь объект BankAccount напрямую.Никакого преобразования, никакого окружения, просто передайте все это представлению.Такое разделение, которое вы сделали (для меня), похоже на стрельбу из пушек по мухам ...

Мои аргументы:

  • ваш взгляд способен отображать только BankAccounts, почемуне передать объект, который он отображает?
  • это делает ваш интерфейс очень понятным, требуется только одно свойство: @property(...) BankAccount *bankAccount;
  • (EDIT) передача объекта инкапсулирует зависимостимежду всеми вашими свойствами.Они не независимы, они формируют банковский счет.Это должно быть видно.
  • преобразование не требуется, интерфейс не нужно менять, если вы расширяете модель
  • , очень очень сильное разделение между моделью и представлением было необходимо, только если ваше представлениебыл независим от данных, которые он отображает.Нет смысла анонимизировать представление, которое может отображать только один очень специфический тип данных: банковский счет.
  • Все преобразования будут иметь смысл только в том случае, если вы составите свое представление о нескольких повторно используемых компонентах.Похоже, что это просто ненужная работа.
  • MVC все еще сохраняется: модель не знает контроллер или представление, представление не знает непосредственно контроллер, контроллер передает данные из представления в модель и реагирует на действия.

Если вы не хотите передавать класс напрямую, спроектируйте протокол, который инкапсулирует все свойства, необходимые представлению, от объекта банковского счета и должен реализовать класс BankAccount. Однако, это имеет смысл, только если вы (планируете) передавать различные виды классов в качестве данных в представление.Настолько разные, что эти классы не имеют общего суперкласса, способного иметь все эти свойства.Если есть только этот простой класс или унаследованные классы, оставайтесь с самым простым решением: передать учетную запись напрямую.

Чтобы иметь возможность инициировать перерисовку изменений, я предлагаю вам использовать Key-Value-Observation.Это очень чистый способ сохранить анонимность и необходимость писать очень мало кода.В вашем методе init в представлении сделайте следующее для каждого свойства, которое вы хотите наблюдать:

[self addObserver:self forKeyPath:@"bankAccount.<property>" withOptions:0 context:@"redraw"];

Затем вы реализуете observeValueForKeyPath...:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == @"redraw") {
        [self setNeedsDisplay];
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

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

1 голос
/ 27 августа 2010

То, как я смотрю на парадигму MVC (и помните, это просто парадигма - она ​​открыта для интерпретации ) - это то, что Модель ничего не знает о представлении, а представление ничего не знает о модели.Они не должны напрямую взаимодействовать;строго говоря, в вашем представлении не должно быть экземпляра вашей модели.

Именно здесь контроллер становится важным.Я собираюсь притвориться, что у вашего BankAccountView есть несколько ярлыков для отображения информации об учетной записи, и, возможно, табличное представление для отображения всех транзакций по счету (давайте представим, просто для иллюстрации).Тогда у вас будет что-то вроде этого:

MyBankAccountViewController - это подкласс UIViewController ( C в MVC), чье представление является экземпляром BankAccountView.Ваш контроллер представления также имеет экземпляр BankAccount.В соответствующее время (например, -viewDidLoad) вы захотите заполнить свое представление (и его подпредставления) информацией из вашей BankAccount модели (self.bankAccountView.accountNameLabel.text = self.myBankAccount.name или чего-то еще).

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

Когда в вашем представлении происходит что-то, что должно изменить вашу модель (например,пользователь нажимает кнопку «Закрыть эту учетную запись»), «событие» будет отправлено из представления в контроллер (через делегирование, целевое действие или другой выбранный вами механизм).Затем контроллер решает, что делать, например, [self.bankAccount closeBankAccount];.

Как я уже сказал, именно так я интерпретирую MVC (я рассматриваю его строго и педантично), и это может усложнить ваш код больше, чем просто передатьмодель напрямую.Если вы просто собираетесь использовать это представление точно в одном месте и никогда не планируете использовать его повторно, то переход напрямую будет, вероятно, более простым.Просто имейте в виду, что это за счет усложнения повторного использования в будущем (что является одним из ключевых преимуществ MVC: ваши модели и ваши представления должны быть повторно использованы; ваш контроллер не будет).

...