美文网首页
iOS 重构: 视图子元素动态化

iOS 重构: 视图子元素动态化

作者: SoaringHeart | 来源:发表于2020-06-26 12:48 被阅读0次

    当我们布局时,总需要布局各种各样的子视图(UIView/UIImageView/UIButton/UIlabel 及其子类),随思考有没有一种方法通过字符串/类型为参数生成子视图的方法实现,然后子视图还可以二次属性设置,经过不断(半年时间)思考,然后在一个周末,灵光一闪,在 swift 中泛型首先突破实现预期效果,(以九宫格视图为例)代码如下:

    //
    //  UIView+Add.swift
    //  SwiftTemplet
    //
    //  Created by Bin Shang on 2018/8/27.
    //  Copyright © 2018年 BN. All rights reserved.
    //
    
    import UIKit
    public extension UIView{
        
        ///更新各种子视图
        ///更新各种子视图
        final func updateItems<T: UIView>(_ count: Int, type: T.Type, hanler: ((T) -> Void)) -> [T] {
            if count == 0 {
                return []
            }
            
            if let list = self.subviews.filter({ $0.isMember(of: type) }) as? [T] {
                if list.count == count {
                    list.forEach { hanler($0) }
                    return list
                }
            }
            
            subviews.filter { $0.isMember(of: type) }.forEach { $0.removeFromSuperview() }
            
            var arr: [T] = [];
            for i in 0..<count {
                let subview = type.init()
                subview.tag = i
                self.addSubview(subview)
                arr.append(subview)
                
                hanler(subview)
            }
            return arr;
        }
        
        ///更新各种子类按钮
        final func updateButtonItems<T: UIButton>(_ count: Int, type: T.Type, hanler: ((T) -> Void)) -> [T] {
            return updateItems(count, type: type) {
                if $0.title(for: .normal) == nil {
                    $0.titleLabel?.font = UIFont.systemFont(ofSize: 15)
                    $0.setTitle("\(type)\($0.tag)", for: .normal)
                    $0.setTitleColor(.black, for: .normal)
                    $0.setBackgroundColor(.gray, for: .disabled)
                }
                hanler($0)
            }
        }
    
    🌰🌰:
    //
    //  UITableViewCellSudokuButton.swift
    //  SwiftTemplet
    //
    //  Created by Bin Shang on 2020/6/19.
    //  Copyright © 2020 BN. All rights reserved.
    //
    
    import UIKit
    
    ///九宫格
    @objcMembers class UITableViewCellSudokuButton: UITableViewCell {
    
        var numOfRow: Int = 3
        
        var row: Int = 3
    
        var inset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    
        var itemType: UIButton.Type = UIButton.self
    
        // MARK: -lazy
        lazy var items: [UIButton] = {
            return self.contentView.updateItems(self.row*self.numOfRow, type: self.itemType) {
                $0.titleLabel?.font = UIFont.systemFont(ofSize: 15)
                $0.setTitle("\(self.itemType)\($0.tag)", for: .normal)
                $0.setTitleColor(.systemBlue, for: .normal)
            }
        }()
        
        // MARK: -life cycle
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier);
      
        }
            
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder);
            fatalError("init(coder:) has not been implemented")
        }
        
        override func layoutSubviews() {
            super.layoutSubviews();
            
            setupConstraint()
        }
        
        func setupConstraint() {
            if bounds.height <= 0.0 {
                return;
            }
            
            items.snp.distributeSudokuViews(fixedLineSpacing: 5, fixedInteritemSpacing: 10, warpCount: numOfRow, edgeInset: inset)
        }
        
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            
            // Configure the view for the selected state
        }
        
        // MARK: -funtions
        
    }
    
    

    Objc 版本:

    //
    //  UIView+Ext.m
    //  Xcode11Project
    //
    //  Created by Bin Shang on 2020/6/25.
    //  Copyright © 2020 Bin Shang. All rights reserved.
    //
    
    #import "UIView+Ext.h"
    #import "NSArray+Ext.h"
    
    @implementation UIView (Ext)
    
    - (NSArray<__kindof UIView *> *)updateItems:(NSInteger)count aClassName:(NSString *)aClassName handler:(void(^)(__kindof UIView *obj))handler {
        if (count == 0) {
            return @[];
        }
    
        Class cls = NSClassFromString(aClassName);
        NSArray *list = [self.subviews filter:^BOOL(UIView * obj, NSUInteger idx) {
            return [obj isKindOfClass:cls.class];
        }];
        
        if (list.count == count) {
            [list enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (handler) {
                    handler(obj);
                }
            }];
            return list;
        }
        
        for (UIView *view in self.subviews) {
            if ([view isMemberOfClass:cls]) {
                [view removeFromSuperview];
            }
        }
    
        NSMutableArray *marr = [NSMutableArray array];
        for (NSInteger i = 0; i < count; i++) {
            UIView *subview = [[cls alloc]init];
            subview.tag = i;
            
            [self addSubview:subview];
            [marr addObject:subview];
            if (handler) {
                handler(subview);
            }
        }
        return marr;
    }
    
    - (NSArray<__kindof UIButton *> *)updateButtonItems:(NSInteger)count aClassName:(NSString *)aClassName handler:(void(^)(__kindof UIButton *obj))handler {
        return [self updateItems:count aClassName:aClassName handler:^(__kindof UIView * _Nonnull obj) {
            if (![obj isKindOfClass:UIButton.class]) {
                return;
            }
    //        NSString *clsName = NSStringFromClass(obj.class);
            UIButton *sender = (UIButton *)obj;
            if (![sender titleForState:UIControlStateNormal]) {
                sender.titleLabel.font = [UIFont systemFontOfSize:15];
                NSString *title = [NSString stringWithFormat:@"%@%@", aClassName, @(obj.tag)];
                [sender setTitle:title forState:UIControlStateNormal];
                [sender setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
            }
            if (handler) {
                handler(obj);
            }
        }];
    }
    
    @end
    
    
    //
    //  NSArray+Ext.m
    //  Xcode11Project
    //
    //  Created by Bin Shang on 2020/6/20.
    //  Copyright © 2020 Bin Shang. All rights reserved.
    //
    
    #import "NSArray+Ext.h"
    
    @implementation NSArray (Ext)
    
    - (NSArray *)map:(id (^)(id obj, NSUInteger idx))handler{
        __block NSMutableArray *marr = [NSMutableArray array];
        [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if (handler) {
                id blockResult = handler(obj, idx) ? : obj;
                [marr addObject:blockResult];
            }
        }];
    //    DDLog(@"%@->%@", self, marr.copy);
        return marr.copy;
    }
    
    - (NSArray *)filter:(BOOL(^)(id obj, NSUInteger idx))handler{
        __block NSMutableArray *marr = [NSMutableArray array];
        [self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if (handler && handler(obj, idx) == true) {
                [marr addObject:obj];
            }
        }];
        return marr.copy;
    }
    
    - (NSNumber *)reduce:(NSNumber *(^)(NSNumber *num1, NSNumber *num2))handler{
        __block CGFloat result = 0.0;
        [self enumerateObjectsUsingBlock:^(NSNumber *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx < self.count - 1) {
                NSNumber *num1 = idx == 0 ? obj : @(result);
                NSNumber *num2 = self[idx+1];
                if (handler) {
                    result = handler(num1, num2).floatValue;
    //                DDLog(@"handler_%@_%@_%@_%@",num1, num2, handler(num1, num2), @(result));
                }
            }
        }];
        return @(result);
    }
    
    @end
    
    🌰🌰:
    //
    //  NNHomeViewController.m
    //  MasonryExtend_Example
    //
    //  Created by Bin Shang on 2019/12/13.
    //  Copyright © 2019 shang1219178163. All rights reserved.
    //
    
    #import "NNHomeViewController.h"
    //#import "Masonry.h"
    #import "MasonryExtend.h"
    
    #import "UIView+Ext.h"
    #import "UIButton+Ext.h"
    
    @interface NNHomeViewController ()
    
    @end
    
    @implementation NNHomeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.title = @"Sudoku";
            
        NSArray *list = [self.view updateItems:9 aClassName:@"NXButton" handler:^(UIView * _Nonnull obj) {
            if (![obj isKindOfClass:UIButton.class]) {
                return;
            }
            NSString *clsName = NSStringFromClass(obj.class);
            UIButton *sender = (UIButton *)obj;
            sender.titleLabel.font = [UIFont systemFontOfSize:15];
            NSString *title = [NSString stringWithFormat:@"%@%@", clsName, @(obj.tag)];
            [sender setTitle:title forState:UIControlStateNormal];
            [sender setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
            [sender setBackgroundColor:UIColor.whiteColor forState:UIControlStateNormal];
            [sender setBackgroundColor:UIColor.systemBlueColor forState:UIControlStateHighlighted];
            [sender setBackgroundColor:UIColor.grayColor forState:UIControlStateDisabled];
        }];
    
        [list mas_distributeSudokuViewsWithFixedLineSpacing:5
                                      fixedInteritemSpacing:5
                                                  warpCount:3
                                                      inset:UIEdgeInsetsMake(10, 10, 10, 10)];
        
    //    [list mas_distributeSudokuViewsWithFixedItemWidth:120
    //                                      fixedItemHeight:120
    //                                            warpCount:3
    //                                                inset:UIEdgeInsetsMake(10, 10, 10, 10)];
    
        self.view.backgroundColor = UIColor.systemGreenColor;
    }
    
    @end
    
    

    Swift 源码
    Objc 源码

    Simulator Screen Shot - iPhone 6s Plus - 2020-06-25 at 16.22.20.png Simulator Screen Shot - iPhone 6s Plus - 2020-06-25 at 16.22.47.png

    相关文章

      网友评论

          本文标题:iOS 重构: 视图子元素动态化

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