我正在尝试通过将属于 UIView
的代码与属于 UIViewController
的代码分开来重新组织早期项目。一个热门问题(found here)的答案似乎并没有解决我需要做的事情,所以让我用两个例子来说明我的问题。
- 示例 1
这里的方法setBackground:zone
更改 View 的背景颜色以指示应用程序中的各种状态。 如下所示的方法当前有效,我想将代码重新定位到它所属的 View 。
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 来引用 中
(相当于原始项目中的zone
的值来初始化 CustomView
中的背景颜色ViewControllerViewControllers
已经获取并设置了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
无法引用 zone
设置通过 ViewController 中的
但我不明白为什么。setSelected:zone
。
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 是否是最好的方法 - 尤其是这个:
The biggest danger here is that by asking for data from an object, you are only getting data. You’re not getting an object—not in the large sense. Even if the thing you received from a query is an object structurally (e.g., a String) it is no longer an object semantically. It no longer has any association with its owner object. Just because you got a string whose contents was “RED”, you can’t ask the string what that means. Is it the owners last name? The color of the car? The current condition of the tachometer? An object knows these things, data does not.
那么如何将消息从父 UIViewController 传递到 UIView 类中的方法?
最佳答案
VC 完全可以设置其 View 的属性。这是第一个示例的带注释的代码...
- (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
子类作为该 View Controller 的 View ,那也没关系。您可以使用自定义实例替换 View ,也可以使用具有相同框架的 subview 覆盖默认 View 。但是给 View 一个指向它的 View Controller 的指针是不明智的(更不明智的是将此指针称为“父”)
因此,对于第二个示例,自定义 View 类应该大大简化......
@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
)。
管理此 View 的 View Controller 现在可以简化为:
- (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;
//}
关于ios - 使用 getter 和 setter 是否可以将消息从父 UIViewController 传递到 UIView 类中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43218839/