美文网首页iOS奋斗ios奇门杂招iOS
最好用的 iOS 快速布局UI库

最好用的 iOS 快速布局UI库

作者: 猫执旅人 | 来源:发表于2017-02-11 16:14 被阅读9067次

    NerdyUI

    github: https://github.com/nerdycat/NerdyUI

    Cupcake (Swift 版本)

    github: https://github.com/nerdycat/Cupcake

    相关文章:
    NerdyUI 使用小技巧


    序言

    众所周知,UI在一个App中所占的比重是很大的,如果能快速的布局UI,就能大大的提高App的整体开发效率,NerdyUI正是基于这个理由创建的。

    NerdyUI使用非常紧凑的链式语法,提供一些常用但系统控件又缺失的功能,更为简便的约束创建方式和更好理解的布局系统,势必能大大减少您的代码量和开发时间。


    快速创建 NSString, UIFont, UIColor, UIImage 和常用的 structs

    你可以用 Str() 来转换大部分类型到NSString。同理,你可以用 Log() 来打印大部分的变量。

    Str(100);                    //@"100"
    Str(3.14);                  //@"3.14"
    Str(@0.618);                  //@"0.618"
    Str(view.frame);              //@"{{0, 0}, {100, 100}}"
    Str(view.center);            //@"{50, 50}"
    Str(_cmd);                  //@"viewDidLoad"
    Str(NSString.class);          //@"NSString"
    Str("C-String");              //@"C-String"
    Str(@"1 + 1 = %d", 1 + 1);  //@"1 + 1 = 2
    
    Log(100);
    Log(3.14);
    Log(@0.618);
    Log(view.frame);
    ...
    Log(@"1 + 1 = %d", 1 + 1);
    
    //拼接字符串
    @"1".a(@"2").a(3).a(nil).a(4.0f).a(@5).a(@"%d", 6);    //@"123456"
    

    你可以用 AttStr() 来创建NSAttributedString。

    AttStr(@"hello, 101").match(@"[0-9]+").underline;  //给101加下划线
    AttStr(@"A smile ", Img(@"smile"), @" !!");     //带图片的NSAttributedString
    

    你可以用 Fnt() 来创建UIFont。

    Fnt(15);                     //[UIFont systemFontOfSize:15]
    Fnt(@15);                   //[UIFont boldSystemFontOfSize:15]
    Fnt(@"body");               //UIFontTextStyleBody
    Fnt(@"Helvetica,15");       //helvetica font with size 15
    

    你可以用 Color() 来创建UIColor。

    Color(@"red");              //[UIColor redColor]
    Color(@"0,0,255");          //RGB color
    Color(@"#0000FF");          //Hex color
    Color(@"random");            //random color
    
    //以上这些还可以有一个可选的alpha参数
    Color(@"red,0.5");            //red color with alpha 0.5
    Color(@"0,0,255,0.8");        //blue color with alpha 0.8
    ...
    
    Color(Img(@"pattern"));       //pattern image color
    

    你可以用 Img() 来创建UIImage。

    Img(@"imageName");          //[UIImage imageNamed:@"imageName"]
    Img(@"#imageName");        //加上#号会返回一个可拉伸的图片,拉伸位置在图片中心
    Img(@"red");                  //返回一个 1x1 大小的红色图片,可用在某些需要纯色图片的地方
    

    你可以用 XY(), WH(), XYWH(), Range(), Insets() 来创建CGPoint, CGSize, CGRect, NSRange, UIEdgeInsets。XYWH()Insets() 支持多种创建方式。

    CGPoint     p = XY(20, 20);
    CGSize      s = WH(50, 50);
    
    CGRect      f1 = XYWH(20, 20, 50, 50);
    CGRect      f2 = XYWH(f1.origin, f1.size);
    CGRect      f3 = XYWH(f2.origin, 50, 50);
    CGRect      f4 = XYWH(20, 20, f3.size);
    
    NSRange     r = Range(10, 20);
    
    UIEdgeInsets i1 = Insets(10);               //{10, 10, 10, 10}
    UIEdgeInsets i2 = Insets(10, 20);           //{10, 20, 10, 20}
    UIEdgeInsets i3 = Insets(10, 20, 30);       //{10, 20, 30, 20}
    UIEdgeInsets i4 = Insets(10, 20, 30, 40);   //{10, 20, 30, 40}
    

    使用这些宏可以简化一些常见类型的创建过程,更重要的是你可以用同样的方式来设置视图的属性值,稍后你就会明白这是什么意思。

    快速访问frame属性和屏幕大小

    someView.x = 10;
    someView.y = someView.x;
    someView.xy = XY(10, 10);
    someView.w = 50;                //width
    someView.h = someView.w;        //height
    someView.wh = WH(50, 50);
    someView.frame = XYWH(10, 10, 50, 50);
    
    someView.cx = 25;
    someView.cy = someView.cx;
    someView.center = XY(25, 25);
    
    someView.maxX = 60;
    someView.maxY = someView.maxX;
    someView.maxXY = XY(60, 60);
    
    //Screen只是 [UIScreen mainScreen] 的宏定义
    someView.wh = WH(Screen.width, Screen.height);
    

    我猜大部分人都有类似的扩展吧

    快速的创建UI控件

    NerdyUI 使用链式语法来快速的创建和设置 UI 控件。

    UIView *view1 = View.xywh(20, 30, 50, 50).bgColor(@"red").opacity(0.7).border(3, @"3d3d3d");
    UIView *view2 = View.xy(80, 30).wh(view1.wh).bgColor(@"blue,0.7").borderRadius(25).shadow(0.8).onClick(^{
        Log(@"view2");
    });
    
    viewview
    UIImageView *moose = ImageView.img(@"moose").x(20).y(100).shadow(0.6, 2, -3, -1);
    UILabel *quiz = Label.str(@"%d+%d=?", 1, 1).fnt(@17).color(@"66,66,66").fitSize.x(moose.maxX + 10).cy(moose.cy);
    
    moosemoose
    //如果后续不需要再访问 title 的属性,定义为 id 可以减少一些代码量
    id title = AttStr(@"TAP ME").fnt(15).underline.range(0, 3).fnt(@18).color(@"random");
    UIButton *button1 = Button.str(title).insets(5, 10).fitSize.border(1).xy(20, 150).onClick(^(UIButton *btn) {
        //Exp() 可在任何位置执行任意代码
        quiz.text = Str(@"%d+%d=%d", 1, 1, Exp(btn.tag += 1)); 
        [quiz sizeToFit];
    });
    
    UIButton *button2 = Button.str(@"HAT").highColor(@"brown").img(@"hat").gap(8);
    button2.xywh(button1.frame).x(button1.maxX + 10).borderRadius(5).bgImg(@"blue,0.5").highBgImg(@"orange");
    //.highBgImg() 可以用来设置 UIButton 的 highlightedBackgroundColor,这是一个非常有用的功能
    
    buttonbutton
    id pinField = TextField.x(button1.x).y(button1.maxY + 15).wh(170, 30).onChange(^(NSString *text) {
        //这里的 self 已经自动做了 weakify 处理, 不用担心会有引用循环
        [(id)[self.view viewWithTag:101] setText:text];
    }).numberKeyboard.maxLength(4).hint(@"pin code").fnt(15).roundStyle;
    
    id textView = TextView.xywh(20, 240, 170, 100).border(1).insets(8).hint(@"placeholder").fnt([pinField font]).tg(101);
    
    inputinput

    正如你所看到的,大部分链式属性还是比较简单明了的。有一些属性非常的灵活,可以接受不同类型的参数。顺便说一下,View 只是 [UIView new] 的宏定义,Label 只是 [UILabel new] 的宏定义,其他几个UI类也一样(就是类名去掉 UI )。

    你可以用 .opacity().tg() 来设置视图的 alpha 和 tag 值.

    你可以用 .x(), .y(), .xy(), .w(), .h(), .wh(), .xywh(), .cx(), .cy(), .cxy(), .maxX(), .maxY(), .maxXY() 等来设置视图的大小和位置。

    你可以用 .touchEnabled, .touchDisabled, .invisible 来设置视图是否可点和是否可见。

    你可以用 .flexibleLeft, .flexibleRight, .flexibleTop, .flexibleBottom, .flexibleLR, .flexibleTB, .flexibleLRTB, .flexibleWidth, .flexibleHeight, .flexibleWH 等来设置autoresizingMask。

    你可以用 .centerAlignment, .rightAlignment 等来设置对齐属性。

    你可以用 .fnt() 来设置字体,它能接受的参数跟 Fnt() 一样。

    你可以用 .str() 来设置 text 或者 attributedText, 它能接受的参数跟 Str() 一样。

    你可以用 .img(), .highImg()u, .bgImg().highBgImg() 来设置 image, highlightedImage, backgroundImage 和 highlightedBackgroundImage。 他们能接受的参数跟 Img() 一样。

    你可以用 .tint(), .color(), .bgColor(), .highColor() 来设置 tintColor, textColor, backgroundColor 和 highlightedTextColor, 它们能接受的参数跟 Color() 一样。

    你可以用 .border(), .borderRadius().shadow() 来设置边框和阴影。

    你可以用 .fitWidth, .fitHeight.fitSize 来改变视图的大小,使它的大小刚好能包含视图的内容。

    你可以用 .onClick() 来给任何视图添加一个单击事件。

    至于 UITextField 和 UITextView, 你可以用 .hint() 来设置 placeholder, .maxLength() 来限制输入文本的长度, .onChange() 来添加一个文本改变事件。

    如果是 UIButton, UITextField 和 UITextView, 你还可以使用 .insets() 来添加一些padding。

    这里列出的只是一部分属性,你可以到对应的扩展头文件里看完整的属性列表。

    UILabel扩展

    以前如果想给UILabel添加行间距,必须使用NSAttributedString。现在你只需要使用 .lineGap() 设置一下就行了。

    另一个很有的扩展功能是链接,你只需要使用 AttStr() 来创建一个NSAttributedString, 并标记其中一部分为 .linkForLabel,那么标记的那部分自动就会变成链接。然后你只需要用 .onLink() 来给UILabel 添加一个链接点击事件就行了。

    id str = @"Lorem ipsum 20 dolor sit er elit lamet, consectetaur cillium #adipisicing pecu, sed do #eiusmod tempor incididunt ut labore et 3.14 dolore magna aliqua.";
    id attStr = AttStr(str).range(0, 5).match(@"lamet").match(@"[0-9.]+").matchHashTag.linkForLabel;
    
    Label.str(attStr).multiline.lineGap(10).xywh(self.view.bounds).onLink(^(NSString *text) {
        Log(text);
    }).addTo(self.view);
    
    labellabel

    快速的创建约束

    有的时候手动修改 frame 会显得很麻烦。NerdyUI 提供一些链式属性和一个跟 Masonry 类似的方式来创建约束。

    你可以用 .fixWidth(), .fixHeight(), .fixWH() 来添加宽高约束。

    你可以用 .embedIn() 来把一个视图嵌入到它的父视图里, 这会添加上下左右的约束。

    你可以用 .horHugging(), .horResistance(), .verHugging(), .verResistance(), .lowHugging, .lowResistance, .highHugging.highResistance 来设置 contentHuggingPriority 和 contentCompressionResistancePriority。当有多个视图在 StackView 里时,可以用这些属性来设置允许哪些视图可以拉伸,哪些视图不可以拉伸。

    对于更复杂的约束, 你可以用 .makeCons(), .remakeCons().updateCons() 来设置约束, 就像Masonry一样。

    ImageView.img(@"macbook").embedIn(self.view).centerMode;
    
    id hello = Label.str(@"HELLO").fnt(@20).wh(80, 80).centerAlignment;
    id mac = Label.str(@"MAC").fnt(@20).wh(80, 80).centerAlignment;
    
    //使用 .makeCons() 之前必须把当前视图加到父视图里,这里使用 .addTo() 来执行此操作
    EffectView.darkBlur.fixWH(80, 80).addTo(self.view).makeCons(^{
        //在 .makeCons() 里你可以直接使用 make 变量,不需要显示的定义它
        make.right.equal.superview.centerX.constants(0);
        make.bottom.equal.superview.centerY.constants(0);
    }).addVibrancyChild(hello).tg(101);
    
    EffectView.extraLightBlur.fixWidth(80).fixHeight(80).addTo(self.view).makeCons(^{
        make.left.bottom.equal.view(self.view).center.constants(0, 0);
    });
    
    EffectView.lightBlur.addTo(self.view).makeCons(^{
        make.size.equal.constants(80, 80).And.center.equal.constants(40, 40);
    }).addVibrancyChild(mac);
    
    id subImg = Img(@"macbook").subImg(95, 110, 80, 80).blur(10);
    ImageView.img(subImg).addTo(self.view).makeCons(^{
        make.centerX.top.equal.view([self.view viewWithTag:101]).centerX.bottom.constants(0);
    });
    
    constraintsconstraints

    快速布局

    手动给每个视图添加约束稍微想一下就知道会很麻烦。幸好大部分的 UI 可以用 HorStack()VerStack() 来实现。使用这两个简易版 StackView,加上上面介绍的那几个属性,很多时候你根本不需要手动显示的创建任何约束。

    _indexLabel = Label.fnt(17).color(@"darkGray").fixWidth(44).centerAlignment;
    _iconView = ImageView.fixWH(64, 64).borderRadius(10).border(Screen.onePixel, @"#CCCCCC");
    
    //用 .preferWidth() 来设置 preferredMaxLayoutWidth,有助于提高性能
    _titleLabel = Label.fnt(15).lines(2).preferWidth(Screen.width - 205);
    _categoryLabel = Label.fnt(13).color(@"darkGray");
    
    _ratingLabel = Label.fnt(11).color(@"orange");
    _countLabel = Label.fnt(11).color(@"darkGray");
    
    _actionButton = Button.fnt(@15).color(@"#0065F7").border(1, @"#0065F7").borderRadius(3);
    _actionButton.highColor(@"white").highBgImg(@"#0065F7").insets(5, 10);
    _iapLabel = Label.fnt(9).color(@"darkGray").lines(2).str(@"In-App\nPurchases").centerAlignment;
    
    //.gap() 会在每一个StackView Item 之间添加间隙
    id ratingStack = HorStack(_ratingLabel, _countLabel).gap(5);
    id midStack = VerStack(_titleLabel, _categoryLabel, ratingStack).gap(4);
    id actionStack = VerStack(_actionButton, _iapLabel).gap(4).centerAlignment;
    
    HorStack(
             _indexLabel,
             _iconView,
             @10,           //使用NSNumber可在两个 Item 之间添加间隙
             midStack,
             NERSpring,     //NERSpring是一个特殊的变量,它相当于一个弹簧,保证actionStack始终停留在最右边
             actionStack
    ).embedIn(self.contentView, 10, 0, 10, 15);
    
    appcellappcell

    这里我们模仿 AppStore 排行榜来创建一个类似的 Cell 。可以看出 HorStack (横向) 和 VerStack (竖向) 的用法非常的简单。你只需要找出最小的 Stack ,然后把它嵌到上一层的 Stack 里,重复这个过程直到最外层的 Stack 用 embedIn 来添加到它的父视图里。最后你还可以给这些视图加上一些间隙(gap)。

    使用 "Debug View Hierarchy" 可以看到这些视图是怎么嵌套再一起的。

    appcell2appcell2

    一旦布局完,剩下的就是设置要显示的内容,其他的都不需要再动了。

    轻量级 Style

    大部分链式属性都可以设置为 style。

    //全局Style
    Style(@"h1").color(@"#333333").fnt(17);
    Style(@"button").fixHeight(30).insets(0, 10).borderRadius(5);
    //局部Style
    id actionButtonStyle = Style().styles(@"button h1").bgImg(@"red").highBgImg(@"blue").highColor(@"white");
    

    这里我们创建了两个全局 Style 和一个局部 Style。局部 Style 使用 .styles() 来继承那两个全局 Style。创建完之后,全局 Style 可以使用 Style 名来全局引用,局部 Style 只能使用变量名来引用。所有的 UIView(及其子类) 和 NSAttributedString 都可以引用这些 Style。

    id foo = Label.styles(@"h1").str(@"hello world");
    id bar = Button.styles(actionButtonStyle).str(@"Send Email");
    

    其他

    你可以用 PlainTVGroupTV 来创建静态的 UITableView,比如说设置页面。

    PlainTV(Row.str(@"Row1"), Row.str(@"Row2"), Row.str(@"Row3")).embedIn(self.view);
    

    你可以用 AlertActionSheet 来创建并显示 UIAlert 和 UIActionSheet。

    Alert.title(@"Title").message(@"Message").action(@"OK",^{}), cancel(@"Cancel").show();
    ActionSheet.title(@"Title").message(@"Message").action(@"OK",^{}), cancel(@"Cancel").show();
    

    对于NSArray, 我们提供了 .forEach(), .map(), .filter().reduce() 等这几个链式属性。

    id result = @[@1, @2, @3, @4].map(^(NSInteger n) {
        return n * 2;
    }).filter(^(NSInteger n) {
        return n < 5;
    }).reduce(^(NSInteger ac, NSInteger n) {
        return ac + n;
    });
    

    注意

    在链式属性里直接使用中文字符串常量会导致后续的自动补全提示失效,一个解决方案是把中文字符串单独拿出来定义为一个变量,或者把 .str(), .hint() 等 放在最后面。

    当你使用 .onClick(), .onLink(), .onChange().onFinish() 时, 里面的 self 已经做了 weakify 处理了,所以你不需要担心会有引用循环问题。有时候你可能需要对它做个强引用来保证它不会被提前释放。这几个属性除了可以传一个 block 之外,还可以传一个方法名来作为回调方法。

    NerdyUI 使用了非常多的宏定义和类别方法,而且为了方便使用没添加任何前缀。虽然所有的名字都是经过精心挑选的,不排除有跟您自己代码或其他第三方库冲突的可能,请注意。

    用CocoaPods安装

    pod "NerdyUI"

    相关文章

      网友评论

      • 舒马赫:挺好的一个库,不过还是推荐使用xml的布局库FlexLib,采用前端布局标准flexbox(不使用autolayout),支持热刷新,国际化等。可以到这里了解详细信息:

        https://github.com/zhenglibao/FlexLib
      • 西门吸雪:make备用。
      • ChinaJosn:感觉还不错 可以借鉴借鉴:+1:
      • 走进科学:onClick的block里面打的断点执行时机不对如何解决
        走进科学:@猫执旅人 self.view.onClick(self, ^{});这样调用就报错。
        走进科学:@猫执旅人 调用view的onClick,都是直接走宏定义的onClick,不能直接走View的
        - (NERChainableUIViewCallbackBlock)onClick,请问如何解决
        猫执旅人:这是宏定义的通病,似乎无法解决。
      • alan007:Function cannot return function type 'int (__strong id, __strong id)'
        猫执旅人:可否提供完整的 MM_GENERATE_CHAINABLE_TYPES() 定义?
      • alan007:MM_GENERATE_CHAINABLE_TYPES(UIButton); 为什么我自己写 报错了说有UIButton 啊
      • 89cf6ce656e9:哎,团队强势推荐用这个,只能来看看啦~

        确实很方便
      • 闭家锁:有对SizeClass支持吗,如何使用SizeClass呢
        猫执旅人:没有对SizeClass进行封装,如果需要用到SizeClass相关功能,直接使用系统的API即可。
      • 看之学之:看完感觉和masonry很像,都是链式。但是用起来可能成本很高,当然用熟了是很爽,大大简便了UI布局。希望继续维护。
      • 猫执旅人:Swift 版本已经发布,欢迎大家使用。
        https://github.com/nerdycat/Cupcake
      • cf02d3bf4496:楼主 我用这个框架 在8.1.2版本的5s上面 布局全都乱了 这个不是支持8.0以上吗
        猫执旅人:经验证 iOS8 并没有什么问题,请大家放心使用。
      • e2aae398569d:似乎跟Masonry有冲突,尤其是使用属性的时候,比如Insets
        猫执旅人:经测试,insets应该是没问题的,虽然Masonry也有insets,而且会被NerdyUI的insets宏替换掉,但因为insets宏可以接受 UIEdgeInsets作为参数,所以是完全兼容Masonry的insets属性的。

        UIButton *button = Button.str("Button").insets(8, 10).bgImg(@"red").addTo(self.view);
        [button mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
        }];

        以上为测试代码,也有可能有其他的情况我没考虑到,欢迎给出代码或者错误提示。
      • 梦翔_d674:Label在非左对齐情况下onLink位置不正确
        猫执旅人:@梦翔_d674 经确认这是一个Bug,解决办法也很简单,把 centerAlignment 放在 str 后面即可。将在以后的版本中修复这个Bug。
        梦翔_d674:@猫管家 NSAttributedString *text = AttStr(@" 注册即表示同意《软件许可及服务协议》").fnt(12).match(@"《软件许可及服务协议》").linkForLabel.color(@"blue");
        self.agreementLabel = Label.addTo(self.view).centerAlignment.str(text).makeCons(^{
        make.height.constants(23);
        make.left.right.End();
        make.bottom.constants(-20);
        }).onLink(@"onLink:");
        猫执旅人:demo里的例子就不是左对齐的呢,可以看一下你的代码吗?
      • 猫执旅人:系列文章之一 《NerdyUI 使用小技巧》已经发布,欢迎查看。
      • yytester:为什么我提示这个啊
        Analyzing dependencies
        [!] Unable to find a specification for `NerdyUI`
        猫执旅人:@yytester
        rm ~/Library/Caches/CocoaPods/search_index.json
        pod search NerdyUI
        这样看能不能找到,如果还是没有就更新到最新的CocoaPods试试:joy:
        yytester:@猫管家 还是报这个...
        Analyzing dependencies
        [!] Unable to find a specification for `NerdyUI`:sob:
        猫执旅人:试试
        pod repo remove master
        pod setup
        pod install
      • yytester:赞..👍
      • 猫执旅人:修复了一个崩溃的bug,如果有用到的麻烦更新到最新版本。
      • yakeracles:很方便实用,多谢楼主
      • 国王or乞丐:无非就是吧控件都封装在一起了,然后用起来很快,不用一个一个属性去做了对吧?
      • 默默_David:兰州,宏定义最好加个前缀吧,确实会有很多和自定义的宏重复
        猫执旅人:哪一些重复了? :joy:
      • iOS_Yee:Mark
      • R0b1n_L33:所看过链式编程撸UI适配最全面的库
        细节里诚意满满
        就像使用用惯了txt改用vim
        即使不受大用依然瑕不掩瑜
        R0b1n_L33:@许久以前 :+1:
        许久以前:宏定义名字没有前缀,太短,容易和现有的宏冲突
        猫执旅人:感谢好评:smile:
      • Albert新荣:这个工具不错
      • 青青子衿卍:给你个star,虽然我是个snap党.但我非常喜欢这个风格,希望能坚持维护.
        猫执旅人:@青青子衿卍 感谢好评和建议!getStyle功能已添加,具体用法请见README。还有Swift4已支持。至于简单的flex-box功能,可结合stack和makeCons来使用:smile:
        青青子衿卍:@猫管家 新项目试用了下,感觉不错.已经弃用snap了. 给出两点小建议 1:既然view可以addStyle,希望也可以getStyle,来达到一个吸管的功能. 2:stack很好用,不过在某些布局里flex-box还是很需要的 另外希望对swift4给予支持,加油!
        猫执旅人:谢谢,一定会持续维护的:blush:
      • 开发者头条_程序员必装的App:感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/8fkxpm 欢迎点赞支持!
        欢迎订阅《猫管家》https://toutiao.io/subjects/185955
      • 夜的v:有用,已赞。感谢分享
      • 寒枫傲天:我项目中做法跟你比较相似,也是链式去扩展UI,以及类似于masonry的frame布局
      • 懒猫的鱼:好久没来 简书 。发现评论的性质没以前好了。有的人说不好,又举不出例子哪里不好。这是作者自己 造的轮子,当然就个人而言 是比较方便的。对于大项目,大团队,一般都有团队自己开发的一套便利开发第三方。个人项目。小团队,更新迭代没那么多的项目。都可以玩玩。
        主要看自己的习惯。我也不喜欢原生的那些啰嗦重复的代码,但确实要考虑与别人合作开发的便利性。
        猫执旅人:感谢评价:blush:
      • 不知蜕变的挣扎:看完还是觉得原生好。。。。
        猫执旅人:我实在是不想写四五行代码就为了创建个 Button 啦:persevere:
      • 22a1cb95edec:Star太少,用这个风险比较大。用第三方要慎重!万一哪天不维护了呢?
        猫执旅人:请放心,一定会持续维护的:blush:
        AirSars:赞同
      • b964a71f5f5c:建议看看这个,这才是最简单的。代码太费劲了。
        http://blog.csdn.net/fatherhui
        b964a71f5f5c:@nickshin 复杂的也可以的,和复杂没关系。
        a66cb0fa1a93:@猫管家 EALayout坑更多,上手曲线也更陡,不忍多说,当然你只跑demo当我没说,实际项目复杂度不只差一个数量级
        猫执旅人:好棒,其实我挺喜欢 UI 跟代码分离的,对应从 Android 或 H5 过来的人来说,这是很自然的。但对于一直只做 iOS 的人来说,这种转变的难度似乎比想象的要大呢。
      • whbalzac:可能感觉没有想象中的好用。
        要使用这个UI库,得记住框架内众多的宏。
        其次代码的可读性并不高,不方便团队的沟通。
        倾向于适合个人开发者。
        whbalzac:@猫管家 你说得挺对的,80%的UI基本上很简便,个人项目试用一下~非常感谢:smile:
        猫执旅人:这算是另一个不足之处,为了简易性而舍弃了可读性。根据我在项目中的实际使用情况,80%的 UI 你都是在用 View, Label, Button 和 ImageView 这4个类,而这几个类中用的最多的是str, fnt, color, bgColor, img, bgImg, lines, onClick 这几个属性,所以只要记住这几个就能应付很多情况了。更重要的一点是 NerdyUI 不会强迫你必须使用它提供的功能,如果你不知道该怎么用,完全可以直接用系统提供的方法。非常感谢提出见解:blush: :blush:
      • 7ce30781ff74:block的自动补全没有,写起来有点麻烦
        乡下二哥:block的快捷方式:inlineBlock
        7ce30781ff74:@猫管家 懒虫没救啦:innocent:
        猫执旅人:block确实没有自动补全,这算是一个不足之处吧。不过这也带来了一些灵活性,接受block的地方可以直接传个方法名来作为回调方法。还有block的参数是可变的,甚至可以不用参数。对应的头文件里详细说明了各种情况,我猜如果经常用的话应该能记住吧😂😂
      • 7ce30781ff74:确实方便,值得使用:blush:
        AirSars:适合个人开发用,团队开发 你难道还要求别人也一定会使用不成

      本文标题:最好用的 iOS 快速布局UI库

      本文链接:https://www.haomeiwen.com/subject/izzthttx.html