Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何在Objective-C中实现链式语法? #4

Open
dabing1022 opened this issue Jan 2, 2015 · 4 comments
Open

如何在Objective-C中实现链式语法? #4

dabing1022 opened this issue Jan 2, 2015 · 4 comments

Comments

@dabing1022
Copy link
Owner

在接触到开源项目 Masonry 后,里面的布局约束的链式写法让我颇感兴趣,就像下面这样

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];

其他语言比如 Lua, 实现链式语法很容易。但在 Objective-C 中,如何实现链式语法呢?

注:这里讨论的链式语法特指的是点链式语法,不同于中括号链式语法,如[[[[someObj method1] method2] method3] method4:someParam]。中括号链式语法相对而言更简单些,每个方法的返回值是下一个方法的发送者即可。

查看 Masonry 源码,起初没看明白,于是搜索了下 Stackoverflow,没有发现类似的问题,便将这个问题发布在了 Stackoverflow 上。这里是地址。

总结了下,贴下代码,做个说明。

//------------------------------------------
@interface ClassB : NSObject
@property(nonatomic, readonly) ClassB *(^ddd)(BOOL enable);

- (id)initWithString:(NSString *)str;

@end

@implementation ClassB

- (ClassB *(^)(BOOL))ddd
{
    return ^(BOOL enable) {
        //code
        if (enable) {
            NSLog(@"ClassB yes");
        } else {
            NSLog(@"ClassB no");
        }
        return self;
    };
}

@end



@class ClassB;
@interface ClassA : NSObject

// 1. 定义一些 block 属性
@property(nonatomic, readonly) ClassA *(^aaa)(BOOL enable);
@property(nonatomic, readonly) ClassA *(^bbb)(NSString* str);
@property(nonatomic, readonly) ClassB *(^ccc)(NSString* str);

@end

@implementation ClassA

// 2. 实现这些 block 方法,block 返回值类型很关键,影响着下一个链式
- (ClassA *(^)(BOOL))aaa
{
    return ^(BOOL enable) {
        //code
        if (enable) {
            NSLog(@"ClassA yes");
        } else {
            NSLog(@"ClassA no");
        }
        return self;
    };
}

- (ClassA *(^)(NSString *))bbb
{
    return ^(NSString *str) {
        //code
        NSLog(@"%@", str);
        return self;
    };
}


// 这里返回了ClassB的一个实例,于是后面就可以继续链式 ClassB 的 block 方法
// 见下面例子 .ccc(@"Objective-C").ddd(NO)
- (ClassB * (^)(NSString *))ccc
{
    return ^(NSString *str) {
        //code
        NSLog(@"%@", str);
        ClassB* b = [[ClassB alloc] initWithString:str];
        return b;
    };
}

@end


// 最后我们可以这样做
id a = [ClassA new];
a.aaa(YES).bbb(@"HelloWorld!").ccc(@"Objective-C").ddd(NO);
@veryitman
Copy link

你的代码能编译通过吗?你有没有试过啊?
returning block that lives on the local....

@veryitman
Copy link

你的代码的确是编译有问题(少了结束的分号), 但是在 ios 工程里面就没有returning block that lives on the local....这个错误,何解?

@dabing1022
Copy link
Owner Author

当时这段代码写的时候没有用xCode,没有编译,但其核心思想是没有问题的。重新在xCode上整理了下,有些分号加上了。注意最后

id a = [ClassA new];
a.aaa(YES).bbb(@"HelloWorld!").ccc(@"Objective-C").ddd(NO);

代码的位置,显然要放在main()函数里面或者自己新建一个类。

@dabing1022 dabing1022 reopened this Sep 6, 2015
@veryitman
Copy link

ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants