【问题标题】:Objective-C Declare vars with ({ ... })Objective-C 用 ({ ... }) 声明变量
【发布时间】:2013-11-01 17:32:30
【问题描述】:

我正在查看REMenu lib 代码,并看到一个变量被声明为 ({ ... }); .. 看起来类似于惰性评估代码的“闭包”.. 我不知道。。谁能给我解释一下?

self.menuWrapperView = ({
        UIView *view = [[UIView alloc] init];
        view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        if (!self.liveBlur || !REUIKitIsFlatMode()) {
            view.layer.shadowColor = self.shadowColor.CGColor;
            view.layer.shadowOffset = self.shadowOffset;
            view.layer.shadowOpacity = self.shadowOpacity;
            view.layer.shadowRadius = self.shadowRadius;
            view.layer.shouldRasterize = YES;
            view.layer.rasterizationScale = [UIScreen mainScreen].scale;
        }
        view;
    });

    self.toolbar = ({
        UIToolbar *toolbar = [[UIToolbar alloc] init];
        toolbar.barStyle = self.liveBlurBackgroundStyle;
        if ([toolbar respondsToSelector:@selector(setBarTintColor:)])
            [toolbar performSelector:@selector(setBarTintColor:) withObject:self.liveBlurTintColor];
        toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        toolbar;
    });

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    这是一个名为“statement expression”的 GNU(非标准)C 语言扩展。 gcc、clang和several other compilers支持语法。

    基本上,它允许您将任意块​​视为单个表达式,其值是块中最后一条语句的值。

    这个扩展最有用的是宏定义。在我看来,您在问题中引用的代码(来自REMenu.m 中的showFromRect:inView: 方法)如果not 使用语句表达式会更好。相反,应该将这些语句表达式中的代码分解为单独的方法。例如:

        self.menuWrapperView = [self newMenuWrapperView];
        self.toolbar = [self newToolbar];
    
    ...
    
    - (UIView *)newMenuWrapperView {
        UIView *view = [[UIView alloc] init];
        view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        if (!self.liveBlur || !REUIKitIsFlatMode()) {
            view.layer.shadowColor = self.shadowColor.CGColor;
            view.layer.shadowOffset = self.shadowOffset;
            view.layer.shadowOpacity = self.shadowOpacity;
            view.layer.shadowRadius = self.shadowRadius;
            view.layer.shouldRasterize = YES;
            view.layer.rasterizationScale = [UIScreen mainScreen].scale;
        }
        return view;
    }
    
    - (UIToolbar *)newToolbar {
        UIToolbar *toolbar = [[UIToolbar alloc] init];
        toolbar.barStyle = self.liveBlurBackgroundStyle;
        if ([toolbar respondsToSelector:@selector(setBarTintColor:)])
            [toolbar performSelector:@selector(setBarTintColor:) withObject:self.liveBlurTintColor];
        toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        return toolbar;
    }
    

    【讨论】:

    • 很好@rob,谢谢。然后,我相信在这种情况下,唯一的好处是组初始化代码。没有?
    • 我正在努力不喜欢这样,但它在我身上成长。 @seufagner 是的——它实际上是说 _menuWrapperView ivar 由这个自包含的代码块初始化,不多也不少。它确实使重构更容易(只需抓住分配+整个范围,剪切...滚动..粘贴)。它也很可读。尾随的 view; 看起来有点奇怪,但我敢打赌,如果省略它,编译器会抱怨得很厉害。
    • @bbum 我们已经有一个语法可以有效地表示“_menuWrapperView ivar 由这个自包含的代码块初始化,不多也不少。”查看我的更新。也许如果语句表达式引用了在封闭函数中定义的大量变量,那么使用将是合理的。在这种情况下,它只引用self,但您必须检查代码才能发现,这(在我看来)使得这里使用语句表达式比函数调用更糟糕。
    • @robmayoff 我非常同意您的编辑。但是,问题在于,许多视图实际上是其他视图的集合体,每个其他视图应该只有一个实例。这些实例是在封装视图的实例化时创建的,它们的生命周期与容器紧密绑定。因此,“类似工厂”的方法并没有真正的价值。可以使用延迟初始化(即第一次执行 getter),但这只会使实例化相对不确定。将所有视图配置代码保存在 -configureSubviews 方法中似乎很自然。
    猜你喜欢
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2014-03-16
    相关资源
    最近更新 更多