Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best (designwise) way to pass an NSArray of model objects to a view object?

I have a BankAccount model class that contains data like account number, bank name, transactions, etc. The transactions are each instances of the Transaction class and contained in the transactions NSArray.

I also have a BankAccountView that displays all this in a single view. Right now I'm passing all the data as separate variables (ie. bankAccountView.accountNumber = bankAccount.accountNumber, bankAccountView.bankName = bankAccount.bankName).

The problem/dilemma arises when I need to pass the transactions to the view. I learned to keep the model and view classes separated, so I assume it's not a good thing to just pass the transactions array of BankAccount to BankAccountView, since that array contains instances of the Transaction model class.

So what I'm doing now is this: I take each Transaction instance, translate it into an NSDictionary, then set bankAccountView.transactions to an NSArray containing those dictionaries. It works and I feel like it's keeping my model and view classes separate, but it also feels overly complex, like I'm writing a lot of code for someting that could be much simpler.

Is there a better way to do this? Thanks in advance.

like image 810
Rits Avatar asked Nov 25 '25 16:11

Rits


1 Answers

I think you took it way too far already and should pass the whole BankAccount object directly. No conversion, no surroundings, just pass it all along to the view. The kind of separation you did (to me) feels a bit like shooting with cannons at flies...

My arguments:

  • your view is capable of displaying BankAccounts only, why not pass the object it's displaying?
  • this makes your interface very clear, only one property is needed: @property(...) BankAccount *bankAccount;
  • (EDIT) passing an object encapsulates the dependencies between all your properties. They ain't independent, they form a bank account. This should be visible.
  • no conversion is needed, the interface does not need to be changed if you extend the model
  • the very very strong division between model and view was needed only if your view was independent from the data it's displaying. There is no point in anonymizing a view that can display only one very specific type of data: a bank account.
  • All the conversion would only make sense if you compose your view of several reusable components. You don't seem to so this is simply unnecessary work.
  • MVC is still preserved: Model does not know controller or view, view does not directly know controller, controller passes data from view to model and reacts to actions.

If you do not want to pass the class directly, design a protocol that encapsulates all properties the view needs from a bank account object and have the class BankAccount implement it. However, this only makes sense if you (plan to) pass different kinds of classes as data to the view. So different that these classes don't share a common superclass capable of all these properties. If there is only this simple class or inherited classes, stay with the simplest possible solution: pass the account directly.

In order to be able to trigger redraw on changes, I suggest you use Key-Value-Observation. It's a very clean way to keep the anonymity and having to write very few code. In your init method in the view do the following for each property you'd like to observe:

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

Then you implement 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];
    }
}

I find this to be a very clean method with very little overhead, which I happen to heavily use in my own projects.

like image 147
Max Seelemann Avatar answered Nov 27 '25 08:11

Max Seelemann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!