视图 x 位置的通知

Posted

技术标签:

【中文标题】视图 x 位置的通知【英文标题】:notification for a view x position 【发布时间】:2014-09-03 16:55:24 【问题描述】:

在我正在为我的项目开发的幻灯片菜单中,我想在内容视图滑出时添加一个黑色视图。为此,我需要创建一种方法来连续检查视图 x 位置并使黑色层变暗或变亮。此视图的位置与内容视图相同。 我想我可以像这样使用 NSNotificationCenter:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incomingNotification:) name:@"notification" object: darkViewController.view.frame.origin.x]];    

还有一个方法:

- (void) incomingNotification:(NSNotification *)notification
// the dark layer alpha will be 0 at origin=0 and 0.8 at bounds.size.width
float alphaToUse =  (darkViewController.view.frame.origin.x / self.view.bounds.size.width) * 0.8;
[darkViewController.view setAlpha:alphaToUse];

问题是我必须使用一个对象作为参数。 我是通知的新手,所以我问:将它们用于这种事情是错误的吗? 用其他方式解决这个问题会更好吗?

编辑: 按照丹尼斯的建议,我现在正在尝试使用键值观察解决方案。 我的应用程序结构如下: MenuViewController-->ContainerViewController-->DarkViewController

在 MenuViewController.m 中:

@interface MenuViewController ()

@property (strong,nonatomic) ContainerViewController *containerViewController;
@property (strong,nonatomic) DarkViewController *darkViewController;

@end

@implementation MenuViewController

@synthesize containerViewController,darkViewController;

# pragma mark - Views

- (void)viewDidLoad
[super viewDidLoad];    
containerViewController = [[ContainerViewController alloc]init];
[self addChildViewController:containerViewController];
[self.view addSubview:containerViewController.view];
[containerViewController didMoveToParentViewController:self];

darkViewController = [[DarkViewController alloc]init];
[containerViewController addChildViewController:darkViewController];
[containerViewController.view addSubview:darkViewController.view];
[darkViewController didMoveToParentViewController:containerViewController];

[UIView animateWithDuration:slideDuration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^
    [darkViewController.view setAlpha:0.7];
    containerViewController.view.frame = CGRectMake(self.view.frame.size.width - slideWidth, 0, self.view.frame.size.width, self.view.frame.size.height);

                 completion:^(BOOL finished) 
                     if (finished) 
                     
                 ];

[darkViewController addObserver:self forKeyPath:@"darkViewController.view.frame.origin.x" options:NSKeyValueObservingOptionNew context:nil];


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary *)change context:(void *)context

NSLog(@"x is changed");

当我运行它时,我得到了这个异常:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<DarkViewController 0x10962d280> addObserver:<MenuViewController 0x10922c890> forKeyPath:@"darkViewController.view.frame.origin.x" options:1 context:0x0] was sent to an object that is not KVC-compliant for the "darkViewController" property.'

好的,我似乎在这个例子Notificationsin ios找到了一个解决方案

我刚刚在 ContainerViewController 的 viewDidLoad 中添加了这个

    [self addObserver:self forKeyPath:@"view.frame" options:0 context:nil];

并使用 for 循环实现观察者方法以查找我的 DarkViewController 视图

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

for (UIViewController * vc in self.childViewControllers) 
    if ([vc isKindOfClass:[DarkViewController class]]) 
        float alphaToUse =  (self.view.frame.origin.x / self.view.bounds.size.width)  * 0.8;
        [vc.view setAlpha:alphaToUse];
    


现在我只需要了解将 removeObserver 方法放在哪里,因为我的 ContainerViewController 将始终被加载...

【问题讨论】:

【参考方案1】:

iOS 中还有另一种机制来处理这种事情,称为键值编码和键值观察。

来自通知中心文档:

在设计应用程序时,不要简单地假设您应该发送通知以与相关方进行沟通。您还应该考虑替代方案,例如键值观察、键值绑定和委托。

在 OS X 10.3 版中引入了键值绑定和键值观察,并提供了一种松散耦合数据的方式。通过键值观察,您可以请求在另一个对象的属性发生更改时得到通知。与常规通知不同,未观察到的更改不会造成性能损失。被观察对象也不需要发布通知,因为键值观察系统可以自动为您做,尽管您仍然可以选择手动做。

因此,如果您在制作幻灯片菜单动画时有另一个通知观察者,则可能会降低其处理性能。

最好的解决方案是调用动画块内的incomingNotification: 方法(动画执行的方法)。

Apple 文档再次:

虽然键值编码很有效,但它增加了一个比直接方法调用稍慢的间接级别。仅当您可以从它提供的灵活性中受益时,您才应该使用键值编码。

回答已编辑的问题:

This answer 准确描述了您正在尝试做的事情。在某些对象的属性上添加观察者时,对象的名称不应包含在属性键路径中。因此,在您的情况下,添加观察者如下所示:

[darkViewController addObserver:self forKeyPath:@"view.frame" options:NSKeyValueObservingOptionNew context:nil];

当尝试观察一些对象属性时,不要忘记确保对象的类对于该属性是 KVC 兼容的!

并且不要忘记在工作完成后移除观察者。

【讨论】:

我阅读并应用了您链接的答案,但它不起作用。 observeValueForKeyPath 方法没有给我任何更新。好吧,我想我必须找到另一个解决方案。我还阅读了文档并检查了几个示例,但老实说,我无法理解这个 KVC-KVO 是如何工作的......无论如何,谢谢你的时间。

以上是关于视图 x 位置的通知的主要内容,如果未能解决你的问题,请参考以下文章

不同高度的 UITableViewCells 将其附件视图放置在不同的 X 位置

设置视图的 X 和 Y onclick 不改变位置

becomeFirstResponder 重置其他视图的 x/y 位置

如何跟踪用户以获取基于位置的推送通知?

在表格视图单元格中查找 UIView 的 x 位置

当 UIView 在窗口中的位置发生变化时是不是有通知?