1

理想情况下,我想编写代码,使我能够确定执行某个功能时所需的视图执行哪些动画,例如(nb,伪代码):

- (void)animateView:(UIView *)view withAnimations:(NSArray *)arrayOfAnimationBlocks

上述(即,期望的)函数将依次执行一系列动画,并且在前一个动画完全执行之前不会执行每个动画。我还可以arrayOfAnimationBlocks在运行时添加和删除动画。

为了做这样的事情,我正在尝试使用以下内容:

[UIView animateWithDuration:duration animations:animationBlock completion:completionBlock];

并且在调用函数时传递所有参数(duration, animationBlock, completionBlock)。

然而...

似乎您无法self从动画块中访问?我的动画块包含:

void (^animationBlock)(void) = ^
{
    NSLog(@"[^animationBlock]");
    [self.viewToAnimate setBounds:CGRectMake(self.viewToAnimate.bounds.origin.x, self.viewToAnimate.bounds.origin.y, self.viewToAnimate.bounds.size.width*2, self.viewToAnimate.bounds.size.height*2)];
};

我的完成块包含:

void (^completionBlock)(void) = ^
{
    NSLog(@"[^completionBlock]");
    [UIView animateWithDuration:duration animations:^{
        [self.viewToAnimate setBounds:CGRectMake(self.viewToAnimate.bounds.origin.x, self.viewToAnimate.bounds.origin.y, self.viewToAnimate.bounds.size.width/2, self.viewToAnimate.bounds.size.height/2)];
    } completion:^(BOOL finished){
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Animation Complete" message:@"The previous animations should be fully completed." delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
        alert.alertViewStyle = UIAlertViewStyleDefault;
        [alert show];
    }];
};

然后我当然有:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0) NSLog(@"Cancel pressed.");
    else
    {
        NSLog(@"buttonIndex = %i", buttonIndex);
    }
}

在两者中animationBlockcompletionBlockXcode 都会给出以下红色错误: (!) Use of undeclared identifier 'self'

4

4 回答 4

2

乔希在他的评论中给出了正确的答案,我将详细说明。以下内容无效:

void (^completionBlock)(void) = ^
{ ... [self something] ... };

@implementation Whatever

...

@end

(与@implementation放置在 的定义之上的相同completionBlock)因为在您声明的范围内completionBlock没有名为 的变量selfself仅存在于类的实例方法中,并引用已调用的特定实例——在一般情况下,它的值不能提前知道。

因此,您可能想要的(假设非 ARC;如果相关,则删除自动释放)类似于:

@implementation Whatever

- (dispatch_block_t)completionBlock
{
     return [[^{ ... [self something] ... } copy] autorelease];
}

@end

它将动态生成一个指向适当自身的块,并按照正常的 getter 规则将其返回。在运行时实际发生的只是生成并存储代表进入块的外部状态的信息包。没有代码生成或类似的东西,所以不要担心成本。但是,您确实需要copy因为块尝试存在于堆栈上,因此如果不移动到堆中就不能安全返回,这就是copy在这种情况下实现的。

对于 UIView 样式的完成块,您同样需要类似的内容:

- (void (^)(BOOL))blockThatTakesABool
{
    return [[^(BOOL var){... [self something] ... } copy] autorelease];
}
于 2012-09-14T23:27:17.617 回答
0

您似乎已经声明了全局变量并将它们分配给块。因此,块是在全局上下文中定义的,并且没有self方法self的(隐藏)参数,因此只存在于方法中。

在全局范围内使用块语法也是没用的。您也可以编写函数而不是块。块存在的真正原因是在 C 中(以及 C++ 和 Objective-C,因为它是基于 C/C++ 构建的)不可能以嵌套方式声明/定义函数。

以下是块的用途:

void foo() { ... }

void bar() 
{ 
  ...
  aFun(foo);
  ... 
}

以上是合法的,但

void bar() 
{ 
   ...
   afun( void foo() { ... } );
   ...
}

是不合法的,因为在 C/C++/Objective-C 中,一个函数不能在另一个函数中定义,也不能在表达式中内联。

许多语言允许您在表达式中内联定义函数,这是一件非常有用的事情,尤其是对于函数式编程。但是 C/C++/Objective-C 没有。

这就是 Apple 为 Objective-C 发明块的原因(并且C++ lambdas与 Apple 的块非常相似,在 C++11 语言的重新定义中被添加到 C++ 中)。实际上,块是可以在表达式中内联定义的匿名函数。在我的第二个示例中,您将使用块来解决问题。

块(和C++ lambdas)为定义内联函数和相应的闭包提供语言原生支持(有很多限制和怪癖,因为闭包在这些语言中也不是原生概念)。

它们使您更容易遵守 Greenspun 的第十条编程规则。(/我等待有人意识到有保证的尾调用优化也会有多大用处)。

于 2012-09-14T21:06:02.033 回答
0

如果您还没有阅读过 Apple 的 View Programming Guide,那么您应该真正阅读一下。尤其是动画部分

以下是直接来自该文档的示例代码:

- (IBAction)showHideView:(id)sender
{
    // Fade out the view right away
    [UIView animateWithDuration:1.0
        delay: 0.0
        options: UIViewAnimationOptionCurveEaseIn
        animations:^{
             thirdView.alpha = 0.0;
        }
        completion:^(BOOL finished){
            // Wait one second and then fade in the view
            [UIView animateWithDuration:1.0
                 delay: 1.0
                 options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                    thirdView.alpha = 1.0;
                 }
                 completion:nil];
        }];
}

您看到带有完成块的部分吗?他们声明/创建与调用函数内联的块。当您第一次开始时,您应该始终查看 Apple 的代码并尽可能密切关注它们。当您获得更多经验时,您可以扩展并尝试其他方式来做到这一点。

于 2012-09-14T23:20:22.453 回答
0

大家好:我在 StackOverflow 上看到了执行多个顺序 UIView 动画的最佳方式?今天,其中包括用户 Yang 使用 CPAnimationSequence 的回答!链接如下。

这看起来很棒!

于 2012-09-16T01:15:16.280 回答