11

我试图了解如何在 iOS 上使用块。我已经阅读了 Apple 的文档,但是像往常一样,它们是模糊和不完整的,并且没有提到一些重要的信息。我也用谷歌搜索但没有成功。这就是我试图做的一个练习来理解这一点。

我创建了一个块来读取字符串并将字符串与之前读取的字符串进行比较。如果字符串不相同,返回YES,如果相同,返回NO。

我就是这样做的:

我在 .h 上声明了这一点

BOOL (^differentStrings)(void);

我在 .m 上声明了这一点,在 viewController 的 viewDidLoad 内

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

这就是我的使用方式:我有一个线程可以做到这一点:

if (differentStrings)
  NSLog (@"strings are different);

这些是我遇到的问题:

  1. 该块总是返回 YES(字符串不同)
  2. 我不愿意在videDidLoad 中声明这个。我应该如何声明它,以便我可以在全局范围内使用它作为一种方法?我应该像使用方法一样放置这个吗?
  3. 我在块内调用方法“getString”。可以吗?
  4. 我觉得在.m 上声明块变量很奇怪。如我所见,我应该在 .h 上声明块变量,然后在 .m 上使用它们。我试图这样做,但收到一个错误。
  5. 我已经在块的第一行设置了一个调试点,但它并没有停在那里;
  6. 块内的 NSlog 行不打印任何内容。没有调用块吗?

你们能帮我解决这个问题吗?

4

2 回答 2

15

您误解了块的工作原理。(好吧,这有点明显。)与previousString指向 NSString 的变量一样,differentStrings也是指向block的变量。不是运行块的结果,而是块本身。也就是说,在你这样做之后:

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

differentStrings是一个指向的变量。因此,当你这样做时:

if (differentStrings)

…您只是检查是否differentStrings包含 0 或 NULL 以外的内容。由于它包含一个块,因此它不是空的,因此它的计算结果为真。

请记住:differentStrings是块变量,而不是 BOOL 变量。它包含一个块(一个函数,如果你愿意的话),当调用它时将返回一个布尔值。因此,为了实际运行该块,您需要调用它。像这样:

differentStrings();

或者,在您的情况下:

if (differentStrings()) {
    NSLog (@"strings are different");
}

编辑:正如评论中所指出的,因为differentStrings它是一个实例变量,所以你需要copy它,就像你调用retain分配给实例变量的任何其他对象一样。(出于技术原因,我现在不会讨论,您应该始终使用copywith 块而不是retain。)同样,您需要release在稍后的某个时间调用它,也许在您的dealloc方法中。

于 2011-01-06T17:21:16.310 回答
4

我不相信您实际上正在执行该块。我认为你的代码应该是

if (differentStrings())
{
    NSLog (@"strings are different);
}

将块视为函数。我认为您只是在检查该块是否已定义,而不是执行它。

此外,如果您不需要访问块外的 NSString,则可以去掉__block限定符并将currentString声明移到块内。

如果您需要有关块的其他资源,我会在 iTunes U 上的高级 iOS 开发课程秋季课程中介绍它们。我在理解 Cocoa 会话中描述了块语法,以及它们在多线程会话中的 Grand Central Dispatch 中的使用。课程笔记还包含一些以不同方式使用块的示例应用程序的链接。

我也不能高度推荐您观看WWDC 2010视频会议 206 - 在 iPhone 上介绍 Blocks 和 Grand Central Dispatch 和 211 - Simplifying iPhone App Development with Grand Central Dispatch。

于 2011-01-06T17:20:35.567 回答