是否使用 getter 和 setter 将消息从父 UIViewController 传递到 UIView 类中的方法?
Posted
技术标签:
【中文标题】是否使用 getter 和 setter 将消息从父 UIViewController 传递到 UIView 类中的方法?【英文标题】:Is using getters and setters the way to pass a message from a parent UIViewController to a method in a UIView class? 【发布时间】:2017-04-04 22:35:18 【问题描述】:我正在尝试通过将属于UIView
的代码与属于UIViewController
的代码分开来重组早期项目。一个热门问题 (found here) 的答案似乎无法解决我需要做的事情,所以让我用两个例子来说明我的问题。
这里的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
在下面的代码中,我尝试使用getter和setter来初始化CustomView
中的背景颜色,以引用ViewController
中zone
的值(在原始项目中适合ViewControllers
已经获取并设置zone
以更改背景颜色)。
CustomView.h
#import <UIKit/UIKit.h>
@interface CustomView : UIView
UIViewController *parent;
int selectedZone;
- (void)setParent:(UIViewController *)parent;
- (int)getSelectedZone;
@end
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;
我可以告诉我的代码上面不起作用,因为CustomView
中的getSelected:zone
不能引用setSelected:zone
在setSelected:zone
中设置的zone
ViewController.
但我不明白为什么。
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 是否是最好的方法——尤其是这个:
这里最大的危险是通过从一个对象请求数据,你 只是获取数据。你没有得到一个对象——不是大的 感觉。即使您从查询中收到的东西是一个对象 在结构上(例如,一个字符串),它在语义上不再是一个对象。 它不再与其所有者对象有任何关联。只是因为 你得到一个内容为“RED”的字符串,你不能问这个字符串 那是什么意思。是业主姓氏吗?车的颜色?这 转速表的现状?一个对象知道这些事情, 数据没有。
那么如何将消息从父 UIViewController 传递到 UIView 类中的方法?
【问题讨论】:
【参考方案1】:vc 设置它的视图属性是完全可以的。这是您的第一个示例的注释代码...
- (void)viewDidLoad
[super viewDidLoad];
// no need to do this, the UIViewController this inherits from creates the view
// int zone = 1; // or 2 or 3;
//self.view = [[UIView alloc] initWithFrame: [UIScreen mainScreen].bounds];
[self setBackgroundColorForZone:zone];
// improved naming for clarity
- (void) setBackgroundColorForZone:(NSInteger)zone
// fine as you have it
switch //...
// ...
如果您有更好的理由开发自定义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;
//
【讨论】:
danh,感谢您的详细解释。这是我在项目中缺少的完美简单的解决方案。我将不得不考虑“给视图一个指向它的视图控制器的指针是不明智的(甚至更不明智地将此指针称为“父”)。 :-) 乐于助人。命名点是 UIView 使用“父级”来指代它出现的视图,而不是管理它的视图控制器。完全保留指针不明智的原因更多地在于设计传统,强大的所有权和信息流从视图控制器到视图,而不是相反.视图有时确实需要在该链上进行反向通信,一种常见的方法是“委托”。以上是关于是否使用 getter 和 setter 将消息从父 UIViewController 传递到 UIView 类中的方法?的主要内容,如果未能解决你的问题,请参考以下文章
用 mapState 和 mapMutations 替换计算的 getter/setter
使用 sqldelight 为 getter 和 setter 加前缀
是否有任何 Maven 插件可用于从 Jhipster 中删除生成类的 getter/setter 并添加 lombok [关闭]