【问题标题】:Xcode - Is this MVC?Xcode - 这是 MVC 吗?
【发布时间】:2012-08-02 20:28:33
【问题描述】:

我是一名兼职记事本网站编码员,正在逐步开发 IOS 应用程序。上周我得到了我的第一台 Mac,并拼凑了一个半工作的应用程序。现在,被SO answer 说服了,我重新开始尝试学习 MVC。我的学习曲线非常陡峭,所以请多多包涵。

我已经阅读了 MVC、层分离、三个框和一些箭头,我明白了。然而,将理论转化为现实世界是令人沮丧的。我看过的大多数示例应用程序似乎都没有使用 MVC。即使是来自 Apple 的 LazyTableImages example 似乎也使用 app delegate 作为让我感到困惑的模型。我在此基础上非常出色simple MVC example

我的应用从网络服务中检索位置标记。我有一个使用 ARC 的选项卡式应用程序。一个标签有一个 Mapkit 地图来显示标记。

保存标记记录的简单类:

@interface MarkerRecord : NSObject

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

一个模型类,包含标记类的集合,为两个视图提供服务。这是我的模型类 .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

}

一个mapViewController类.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 实现吗?

如果是这样:

  • 如何让模型更新控制器(即如何让 MarkersModel.objectLoader 函数调用 mapViewController.putMarkersOnMap)?

我强烈怀疑答案是控制器上的自定义委托,但我无法终生了解如何实现它。我无法将任何例子与我的情况联系起来。我想我在控制器上需要这样的东西:

@class MapViewController;
@protocol MapViewControllerDelegate;

虽然我在做一些额外的问题:

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

我希望这是一个明确且可以接受的问题。谢谢你的耐心,波莉。

【问题讨论】:

    标签: objective-c xcode model-view-controller


    【解决方案1】:

    我上面的代码大纲(开始)是一个体面的 MVC 实现吗?

    按照我的标准,是的

    如何让模型更新控制器

    你是对的,你想使用委托。您声明委托协议以及它是委托的类。因此,扩展您的 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 对象都应该保留自己的Markers 集合,那么不,它应该保持实例级方法

    【讨论】:

    • 这很好;委托的使用非常普遍。如果您有可能让多个控制器对模型的更改感兴趣,那么您可能还想评估的一种替代方法是“键值观察”。 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
    • @PhillipMills 有用的链接,实际上我最近才真正深入了解如何改进我的 MVC 编程,这应该对我有帮助
    • 很棒的信息。非常感谢。
    • 只是为了完成以防万一这对将来的某人有所帮助-@DanF 答案在 MapViewControllor.viewDidLoad 函数中添加一行时效果很好。创建标记模型实例后,我添加了:[markersModel setDelegate:self];
    • @Polly 是的,这是必要的,很抱歉我忘记了这一点。你也可以markersModel.delegate = self;这两行100%等效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多