ios - 使用 getter 和 setter 是否可以将消息从父 UIViewController 传递到 UIView 类中的方法?

标签 ios objective-c uiview uiviewcontroller getter-setter

我正在尝试通过将属于 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 中的背景颜色ViewController(相当于原始项目中的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 无法引用 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/

相关文章:

ios - Swift 4 - 抛出函数的无效转换

ios - 为什么使用 HTML 字符串对 NSAttributedString 的初始调用比后续调用要长 100 多倍?

ios - UICollectionViewCell subview 接收点击安装

ios - Phonegap 3.4.0 和相机插件 (iOS) : CDVPlugin class CDVCamera (pluginName: camera) does not exist 的问题

ios - 在 View 顶部呈现新的半透明 VC

ios - 我将如何使用闭包传递数据?

iphone - 我的应用程序文本的配置文件

objective-c - 更新 Cocos2d 1.0.1 的方法和类

ios - 如果从另一个类调用 removeFromSuperview 则不起作用

ios - CAL层裁剪