iOS一些小技巧 | 二

一,masonry当没有设置lablel右边距的时候, 那么它的宽度是根据字符串长度决定的,但是如果字符串长度过长,但是又不能直接设置右边距,所以给它一个最小的距离,告诉其如果超过的时候怎么显示:
make.right.mas_lessThanOrEqualTo(self.commodBgView.mas_right).offset(-ScaleForSize(20.0));
距离当前commodBgView的右边最小的距离必须为20。

二,masonry,设置其某个view的宽度为其相对view的数字比例,例如:
make.width.equal(superview.mas_width).multipy(1.0/3.0);
让view是父类view的三分之一宽度。

三,UITextFiled或者TextView增加ToolBar,悬停在键盘上方:
为其分配inputAccessoryView,让其跟随键盘显示和隐藏。如下图:

- (void)drawRect:(CGRect)rect {
    // Drawing code    
    //
    if(nil != self.inputAccessoryView) return;;
    UIToolbar *toolBar =[[UIToolbar alloc]initWithFrame:CGRectMake(0.0, 0.0, ScreenWidth, ScaleForSize(80.0))];
    UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc]initWithTitle:@"取消" style:UIBarButtonItemStyleDone target:self action:@selector(numberFieldCancle)];
    cancelBtn.tintColor = HEXCOLOR(0X17abe3);
    UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc]initWithTitle:@"确定" style:UIBarButtonItemStyleDone target:self action:@selector(numberFieldEnter)];
    doneBtn.tintColor = HEXCOLOR(0X17abe3);
    NSArray *items =@[flexSpace,cancelBtn,doneBtn];
    toolBar.items = items;
    [toolBar sizeToFit];
    self.inputAccessoryView = toolBar;
}

四,两个数组,元素是Model,判断是否有相同的元素,一次循环加正则:

- (void)checkedOperate
{
    __weak typeof(self) weakSelf = self;
    [self.checkedModels enumerateObjectsUsingBlock:^(SkyCorsPernModel *cpModel, NSUInteger idx, BOOL * _Nonnull stop) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"corsPern_id = %@",cpModel.corsPern_id];
        NSArray *tempArr = [weakSelf.personTableView.datas filteredArrayUsingPredicate:predicate];
        if(tempArr.count){
            SkyCorsPernModel *tempCheckModel = tempArr.firstObject;
            tempCheckModel.checked = YES;
        }
    }];
}

五,block中地址传递,通过外接传递的地址内部进行一些判断。

@property (nonatomic,copy)void(^complateProgress)(bool *autoHid);
//
bool isHid = NO;
if(self.complateProgress) self.complateProgress(&isHid);
if(isHid){
    [self displaySucLabel];
}
//
IMUploadProgress *progress = [IMUploadProgress uploadProgressViewBegin:^{
    NSLog(@"begin handle");
} progressCpl:^(bool * _Nonnull autoHid) {
    NSLog(@"progress complate");
    *autoHid = NO;
} hiddenHandle:^{
    NSLog(@"hiddenHandle");
}];

六,controller添加子控制器:

//增加子控制器到当前控制器
[self addChildViewController:childViewController];
//添加自控制器的view当当前控制器
[superview addSubview:childViewController.view];
//告诉自控制器,已经添加到父控制器上了,可在自控制器中重写此方法
[childViewController didMoveToParentViewController:self]; 

移除子控制器:
//告诉自控制器即将移除,并且父控制器置为空,自控制器中可重写次方法
[self willMoveToParentViewController:nil];
//将自控制器的view从其superview中移除
[self.view removeFromSuperview];
//从父控制器中移除
[self removeFromParentViewController];

  七,xcode查看当前UI是否造成离屏渲染,渲染的部分会出现黄色:

八,取消执行延迟执行的方法:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(selecter:) object:nil];
取消当前要延时操作的事件。
跟方法performSelector相对应,方法名和参数都一致才能够取消,属于类方法,所以直接NSObject进行调用。

九,layoutSubviews,一般用于:
当自定义 view的frame发生变化时,修改其子view的布局可重写view的layoutSubviews方法,调用时需调用其父类方法[super layoutSubviews];
一般用于输入框输入文字,改变其大小时并且改变textView的大小,例如:

- (void)layoutSubviews {
    [super layoutSubviews];
    self.emojiButton.frame = ...
    self.moreButton.frame = ...
    [UIView animateWithDuration:0.25 animations:^{
        self.textView.frame = ...
    }];
}

layoutSubviews的其他调用时机:
1,当view被添加到父视图中会延迟调用;
2,当view添加子控件时会被调用;
3,当view的frame发生变化时,会被调用;
4,当view子控件的frame发生变化时,会被调用;
5,ScrollView滚动时会触发layoutSubviews方法;
6,当旋转屏幕时会触发layoutSubviews方法;
7,当view直接调用layoutIfNeeded方法时,会立马调用,不会延迟。

十,简单的跑马灯效果:
场景:将UILabel加入到UIScrollView中,Label的text为二倍的字符串,然后设置Label的width和Scroll的ContentSize.width,然后:

    CGFloat speed = 50.0; // 跑马灯速度
    NSTimeInterval duration = (self.scrollView.contentSize.width - self.scrollView.width) / speed;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
    animation.duration = duration;
    animation.repeatCount = HUGE_VALF;
    animation.beginTime = CACurrentMediaTime();
    animation.autoreverses = NO;
    animation.removedOnCompletion = NO;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.toValue = @(0.0);
    animation.fromValue = @(self.notiLabel.size.width/2);
    [self.notiLabel.layer addAnimation:animation forKey:@"animationViewPosition"];


- (void)stopAnimation
{
    [self.notiLabel.layer removeAnimationForKey:@"animationViewPosition"];
}

十一,以下2个方法,如果用方法2去创建对象,容易造成对象内存溢出,因为创建了两个对象。

/// method 1
+ (instancetype)shared
{
    return [[self.class alloc]init];
}

/// method 2
- (instancetype)initWithOtherParams:(NSObject  * _Nullable )params
{
    return [self.class shared];
}

十二,通过宽度计算label的高度,通常用在聊天列表中。先计算出高度,然后重新分配宽高。

    CGFloat maxContentWidth = self.tableViewWidth-BJPViewSpaceM*4 - userCoverImgViewSize - 66.0;
    CGSize messageLabelSize = [self.messageLabel sizeThatFits:CGSizeMake(maxContentWidth, 0)];
    CGFloat messageWidth = MAX(nameLabelSize.width, messageLabelSize.width);
    [self.messageLabel bjl_updateConstraints:^(BJLConstraintMaker *make) {
        make.width.equalTo(@(messageLabelSize.width)).priorityHigh();
        make.height.equalTo(@(messageLabelSize.height)).priorityHigh();
    }];

十三,UITextView增加连接,及点击:

self.replyMsgText.dataDetectorTypes = (message.fromUser.isTeacherOrAssistant ? UIDataDetectorTypeLink : UIDataDetectorTypeNone);
self.replyMsgText.linkTextAttributes = @{NSForegroundColorAttributeName: HEXCOLOR(0X2485FC)};

十四,updateViewConstraints方法,更新controller中self.view中子view的所有约束;
当[self.viewaddSubview subView]的时候自动调用一次;
当执行self.view.setNeedsUpdateConstraints();方法时手动调用一次;
当self.view中的某个view约束需要更新时,可以调用;
所以重写updateViewConstraints的时候必须调super.updateViewConstraints();方法;

自定View中,updateConstraints方法,更新其子view的约束:
1,当[self addSubView:subView]时候会自动调用一次;
2,当执行self.setNeedsUpdateConstraints();方法时,会手动调用一次;
当view中的某个子view约束需要进行更新时,可以重写该方法进行重新布局;
重新updateConstraints方法时,必须调用其父类view的方法,super.updateConstraints();
如下:

一般用于:当屏幕旋转的时候,需要重新布局UI,可调用setNeedsUpdateConstraints方法根据横竖屏重新进行布局。

controller中:
    override func updateViewConstraints() {
        
        v_1.snp.updateConstraints { make in
            make.width.height.equalTo(flag ? 300 : 100);
            make.center.equalToSuperview();
        };
        super.updateViewConstraints();
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        flag = !flag;
        self.view.setNeedsUpdateConstraints();
    }

自定义view中:
    @objc func singleTap(_ tap: UITapGestureRecognizer) -> Void {
        flag = !flag;
        self.setNeedsUpdateConstraints();
    }
    override func updateConstraints() {
        print("++subview updateConstraints++");
        subview_1.snp.updateConstraints { make in
            make.height.width.equalTo(flag ? 200.0 : 50.0);
        };
        super.updateConstraints();
    }

Leave a Reply

Required fields are marked *