2017-04-04 44 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