2017-04-04 46 views
2

我试图通过将属于UIView的代码与属于UIViewController的代码分开来重新组织早期项目。回答一个受欢迎的问题(found here)似乎并没有解决我需要做的事情,让我用两个例子来说明我的问题。使用getters和setters将消息从父UIViewController传递给UIView类中的方法?

  • 实施例1

这里setBackground:zone改变视图的背景颜色,以指示该应用的各种状态的方法。方法如下所示当前有效,我想将代码重定位到它所属的视图。

ViewController.h

#import <UIKit/UIKit.h> 
#import "CustomView.h" 

@interface ViewController : UIViewController { 
} 
@end 

ViewController.m

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    int zone       = 1; // or 2 or 3; 

    self.view       = [[UIView alloc] initWithFrame: [UIScreen mainScreen].bounds]; 
    [self setBackground:zone]; 
} 

- (void)setBackground:(int)zone { 
    switch (zone) { 
     case 1: 
      self.view.backgroundColor = [UIColor orangeColor]; 
      break; 
     case 2: 
      self.view.backgroundColor = [UIColor cyanColor]; 
      break; 
     case 3: 
      self.view.backgroundColor = [UIColor greenColor]; 
      break; 
     default: 
      break; 
     } 
    } 
  • 实施例2

在下面的代码我试着在CustomView上使用getter和setter来引用zone的值ViewController(适当的为ViewControllers在原始项目中已经获得并且设置为zone以改变背景颜色)的值初始化背景颜色。

CustomView.h

CustomView.m

#import "CustomView.h" 

@implementation CustomView 
    - (void)setParent:(UIViewController *)theParent { 
     parent       = theParent; 
    } 

    - (int)getSelectedZone { 
     return selectedZone; 
    } 

    - (id)initWithFrame:(CGRect)frame 
     { 
     self       = [super initWithFrame:[UIScreen mainScreen].bounds]; 
     if (self) { 

     NSLog(@"selectedZone in CustomView is seen as %i", [self getSelectedZone]); 

      int zone     = [self getSelectedZone]; 
      [self setBackground:(int) zone]; 
     } 
     return self; 
    } 

- (void)setBackground:(int)zone { 
    switch (zone) { 
     case 1: 
      self.view.backgroundColor = [UIColor orangeColor]; 
      break; 
     case 2: 
      self.view.backgroundColor = [UIColor cyanColor]; 
      break; 
     case 3: 
      self.view.backgroundColor = [UIColor greenColor]; 
      break; 
     default: 
      break; 
     } 
    } 

ViewController.h

#import <UIKit/UIKit.h> 
#import "CustomView.h" 

    @interface ViewController : UIViewController {  
     int selectedZone; 
    } 

    - (void)setSelectedZone:(int)zone; 
    - (int)getSelectedZone; 

ViewController.m

#import "ViewController.h" 

@implementation ViewController 

    - (void)viewDidLoad { 
     [super viewDidLoad]; 

     int zone      = 1; // or 2 or 3;  
     [self setSelectedZone:(int)zone]; 
     NSLog(@"selectedZone in ViewController is now set to %i", [self getSelectedZone]); 

     self.view      = [[UIView alloc] initWithFrame: [UIScreen mainScreen].bounds]; 

     CustomView *cv     = [[CustomView alloc]init]; 
     [self.view addSubview:cv]; 
    } 

    - (void)setSelectedZone:(int)zone { 
     selectedZone     = zone; 
    } 

    - (int)getSelectedZone { 
     return selectedZone; 
    } 

我可以告诉我的代码以上不起作用,因为getSelected:zoneCustomView不能引用zone通过setSelected:zoneViewController.设置,但我不明白为什么。

2017-04-05 07:04:26.126 ZoneIndicator[1865:1270743] selectedZone in ViewController is now set to 1 
2017-04-05 07:04:26.126 ZoneIndicator[1865:1270743] selectedZone in CustomView is seen as 0 

an article found here甚至让我怀疑使用getter和setter方法是否是最好的方法 - 尤其是这样的:

最大的危险在这里的是,通过询问数据从一个对象,你 是只获取数据。你没有得到一个对象 - 不是在大的 意义上。即使您从查询中收到的东西在结构上是对象 (例如,,一个字符串)它不再是一个对象的语义。 它不再与其所有者对象有任何关联。只是因为 你得到了一个字符串,其内容是“红色”,你不能问字符串 这意味着什么。它是业主的姓氏吗?汽车的颜色? 转速表的当前状况?一个对象知道这些事情, 数据没有。

那么如何将消息从父UIViewController传递给UIView类中的方法?

回答

3

vc设置视图的属性是完全可以的。这里的注释代码,您的第一个例子...

​​

如果你有更好的理由来开发定制UIView子类是视图控制器的观点,没关系,太。您可以使用自定义实例替换视图,也可以使用具有相同框架的子视图覆盖默认视图。但它是不明智的,给个说法的指针,它的视图控制器(甚至更不明智来调用这个指针“父”)

因此,对于你的第二个例子中,自定义视图类应该大大简化...

@interface CustomView : UIView { 
    // commented out bad stuff 
    // UIViewController *parent; 
    // this isn't needed either 
    //int selectedZone; 
} 
// these aren't needed either 
//- (void)setParent:(UIViewController *)parent; 
//- (int)getSelectedZone; 

// just this 
- (void)setBackgroundColorForZone:(NSInteger)zone; 

@end 

而且实现可以使用与第一个示例中相同的方法。它需要一个区域整数和集合的self.backgroundColor(而不是self.view.backgroundColor)。

管理此视图现在可以简化为视图控制器:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    int zone      = 1; // or 2 or 3; 
    // don't need this 
    //[self setSelectedZone:(int)zone]; 
    //NSLog(@"selectedZone in ViewController is now set to %i", [self getSelectedZone]); 

    // never need this 
    //self.view      = [[UIView alloc] initWithFrame: [UIScreen mainScreen].bounds]; 

    // notice the change to init with frame 
    CustomView *cv     = [[CustomView alloc]initWithFrame:self.view.bounds]; 
    [cv setBackgroundColorForZone:zone]; 
    [self.view addSubview:cv]; 
} 

// don't need any of this 
//- (void)setSelectedZone:(int)zone { 
// selectedZone     = zone; 
//} 

//- (int)getSelectedZone { 
// return selectedZone; 
//} 
+0

DANH,感谢您的详细解释。这是我在项目中缺少的完美简单解决方案。我必须考虑“不明智地给视图一个指向它的视图控制器的指针(并且更加不明智地称这个指针为”parent“)。 – Greg

+0

:-)高兴地帮助。命名要点是UIView使用“parent”来引用它出现的视图,而不是管理它的视图控制器。保持指针不明智的原因更多的是关于设计传统,强大的所有权和信息流从*视图控制器*转到*视图,而不是其他方式。意见有时确实需要在该链上反向沟通,而通常的做法是“委托”。 – danh