Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode - Is this MVC?

I'm a part-time notepad website coder taking steps into IOS apps. I got my first mac last week and have cobbled together a half working app. Now, convinced by this SO answer, I am restarting trying to learn MVC. I am on a very steep learning curve so please bear with me.

I have read up on MVC, separation of layers, three boxes and some arrows, I get it. However, translating the theory into the real world is frustrating. Most example apps I have looked at do not seem to use MVC. Even this LazyTableImages example from Apple seems to use app delegate as the model which confuses me. I have built on this excellently simple MVC example.

My app retrieves location markers from a web service. I have a tabbed application using ARC. One tab has a Mapkit map to display the markers.

A simple class to hold a marker record:

@interface MarkerRecord : NSObject

@property (strong, nonatomic) NSDecimalNumber *lat;
@property (strong, nonatomic) NSDecimalNumber *lon;
@property (strong, nonatomic) NSString *des;

A Model class, holding a collection of Marker classes, to serve both views. This is my Model class .h:

@interface MarkersModel : NSObject

- (void)getMarkers; // Send HTTP GET to web service to retrieve JSON markers
- (void)postMarker; // Send HTTP POST to web service to INSERT new marker record

And the implementation:

@interface MarkersModel ()
@property (strong, nonatomic) NSArray *data;
@end

@implementation MarkersModel
@synthesize data;

- (void)getMarkers
{
    // Send HTTP GET to web service to retrieve JSON markers
    ...
}

- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
    // Thanks to Restkit data is an array of Marker classes
    data = objects;

    // Pass data to controller

}

A mapViewController class .h:

#import <MapKit/MapKit.h>
#import "MarkersModel.h"

@interface MapViewController : UIViewController<MKMapViewDelegate> {
    MarkersModel *markersModel;
}

@property (nonatomic, strong) IBOutlet MKMapView *mapView;

@end

And the implementation:

@interface MapViewController ()
@end

@implementation MapViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Create instance of markers model
    markersModel = [[MarkersModel alloc] init];
}

-(void)viewWillAppear:(BOOL)animated
{
    [markersModel getMarkers];
}

- (void)putMarkersOnMap
{
    // To be called by Markers Model 
    ...
}

Here's my main question:

  • Is my code outline above (the beginnings of) a decent MVC implementation?

If so:

  • how do I get the Model to update the Controller ( i.e. how do I get MarkersModel.objectLoader function to call mapViewController.putMarkersOnMap)?

I strongly suspect the answer is a custom delegate on the controller but I cannot for the life of me see how to implement it. I cannot relate any examples to my situation. I think I need something like this on the controller:

@class MapViewController;
@protocol MapViewControllerDelegate;

While I am at it some additional questions:

  • Will I create any dangling pointers - I suspect something should be unsafe_unretained (I am compiling to 4.3)?
  • Is my MarkersModel declaration in the controller class correct? I am concerned that it will not be managed by ARC. I also suspect it is public but should be private.
  • Should the MarkersModel.getMarkers method be static?

I hope this is clear and an acceptable question. Thanks for your patience, Polly.

like image 697
Polly Avatar asked Aug 02 '12 20:08

Polly


People also ask

What is MVC in Xcode?

Model-View-Controller, or MVC for short, is a widely used design pattern for architecting software applications. Cocoa applications are centered around MVC and many of Apple's frameworks are impregnated by the pattern.

Is iOS development MVC?

MVC is the most-known architecture pattern when it comes to iOS development. In this first article, we saw it in action being applied to a small application. We used the naive approach, where each screen is represented by a View Controller.

Does Apple use MVC?

As a new iOS developer, there is a huge amount of information you need to master: a new language, new frameworks and APIs, and Apple's recommended architectural pattern Model-View-Controller, or MVC for short. The MVC pattern is commonplace in iOS development.

What is difference between MVC and MVVM in iOS?

The difference between the MVC and MVVM is View and controller are responsible for calculating the value and assigning the value so the load is more on View and Controller where in MVVM View and Controller are only responsible for assigning the value not calculating the value.


1 Answers

Is my code outline above (the beginnings of) a decent MVC implementation?

By my standards, yes

how do I get the Model to update the Controller

You are correct, you want to use a delegate. You declare the delegate protocol along with the class it is a delegate for. So expanding on your MarkersModel header:

@protocol MarkersModelDelegate<NSObject>
-(void) markersDidUpdate:(MarkersModel*)model;
@end

@interface MarkersModel : NSObject
{
    __weak id<MarkersModelDelegate> delegate;
}

@property(weak,nonatomic) id<MarkersModelDelegate> delegate;

Then in your view controller:

@interface MapViewController : UIViewController<MKMapViewDelegate, MarkersModelDelegate> {

Then in the model implementation:

@implementation MarkersModel

@synthesize delegate;

//...

-(void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
    // Thanks to Restkit data is an array of Marker classes
    data = objects;

    // Pass data to controller
    if( delegate != nil )
    {
        [delegate markersDidUpdate:self];
    }
}

Will I create any dangling pointers - I suspect something should be unsafe_unretained (I am compiling to 4.3)?

Not that I am aware of

Is my MarkersModel declaration in the controller class correct? I am concerned that it will not be managed by ARC. I also suspect it is public but should be private.

You can declare it as private by adding the @private header beforehand:

@interface MapViewController...
{
@private
MarkersModel *markersModel;
...

Should the MarkersModel.getMarkers method be static?

If by static, you mean as a class-level instead of instance-level method, that entirely depends on your implementation. If all MarkersModel objects are supposed to retain the same data, then yes it makes sense to make it class-level. But if each MarkersModel object is supposed to retain its own set of Markers then no, it should remain an instance-level method

like image 70
Dan F Avatar answered Oct 12 '22 06:10

Dan F