Xcode - 这是MVC吗?

5
我是一名兼职的记事本网站编码员,正在进入IOS应用程序领域。上周我得到了我的第一个Mac,并组装了一个半工作的应用程序。现在,受到这个SO答案的启发,我重新开始学习MVC。我正在经历一个非常陡峭的学习曲线,请耐心等待。
我已经研究了MVC、分层、三个方框和一些箭头的概念,我懂了。然而,将理论转化为现实世界是令人沮丧的。我看过的大多数示例应用程序似乎并没有使用MVC。即使是苹果提供的这个LazyTableImages示例也似乎使用app delegate作为模型,这让我感到困惑。我已经在这个简单的MVC示例的基础上进行了优秀的构建。
我的应用程序从Web服务中检索位置标记。我使用ARC创建了一个选项卡应用程序。其中一个选项卡有一个Mapkit地图来显示标记。
一个简单的类来保存标记记录:
@interface MarkerRecord : NSObject

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

一个Model类,持有一组Marker类,以供两个视图使用。这是我的Model类.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

实现方式如下:

@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

}

一个地图视图控制器类 .h:

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

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

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

@end

实现方法:

@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 
    ...
}

以下是我的主要问题:

  • 上述代码概述(开始部分)是否是一个不错的MVC实现?

如果是:

  • 如何使Model更新Controller(即如何使MarkersModel.objectLoader函数调用mapViewController.putMarkersOnMap)?

我强烈怀疑答案是在控制器上使用自定义代理,但我无论如何都看不到如何实现它。我无法将任何示例与我的情况联系起来。我认为我需要在控制器上添加类似于以下内容的内容:

@class MapViewController;
@protocol MapViewControllerDelegate;

顺便问一下几个问题:

  • 我会创建任何悬空指针吗 - 我怀疑应该使用unsafe_unretained(我正在编译到4.3)?
  • 我的控制器类中的MarkersModel声明是否正确?我担心它不会被ARC管理。我还怀疑它是公共的,但应该是私有的。
  • MarkersModel.getMarkers方法应该是静态的吗?

希望这很清楚,也是可以接受的问题。感谢您的耐心,Polly。

1个回答

5

我上面的代码概述(开始实现)是一个不错的MVC实现吗?

按照我的标准,是的。

如何让Model更新Controller?

你说得对,你需要使用代理。你可以在代理类中声明代理协议。因此,在扩展你的MarkersModel头文件时:

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

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

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

然后在您的视图控制器中:

@interface MapViewController : UIViewController<MKMapViewDelegate, MarkersModelDelegate> {

接下来在模型实现中:

@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];
    }
}

我是否会创建任何悬空指针 - 我怀疑某些内容应该是 unsafe_unretained (我正在编译为 4.3 版本)?

据我所知,不会。

我的控制器类中的 MarkersModel 声明是否正确?我担心它不会被 ARC 管理。我还怀疑它是公共的,但应该是私有的。

您可以在前面添加 @private 标头来将其声明为私有:

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

如果说静态方法指的是类级别的而不是实例级别的方法,那么是否应该将MarkersModel.getMarkers方法设置为静态方法就完全取决于你的实现方式。如果所有的MarkersModel对象都希望保留相同的数据,那么将其设置为类级别的方法是有意义的。但是,如果每个MarkersModel对象都希望保留自己的一组标记,则不应将其设置为实例级别的方法。

1
这很好;使用委托非常普遍。如果您有多个控制器对模型的更改感兴趣,您可能还想评估“键值观察”作为另一种选择。http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html - Phillip Mills
@PhillipMills 这是一个有用的链接,我最近一直在深入研究如何改善我的MVC编程,这应该会对我很有帮助。 - Dan F
仅供完成,以便帮助未来有需要的人 - @DanF的答案很好用,只需在MapViewControllor.viewDidLoad函数中添加一行即可。创建markersModel实例后,我添加了:[markersModel setDelegate:self]; - Polly
@Polly 是的,那是必要的,很抱歉我忘记了这一点。你也可以使用 markersModel.delegate = self; 这两行代码是完全等价的。 - Dan F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接