iOS runtime 应用场景

class_addMethod应用场景

iOS runtime 应用场景_第1张图片
屏幕快照 2018-05-24 下午4.37.08.png

如上图,右边弹出的一个毛玻璃视图,点击非玻璃区,毛玻璃页面从右边消失。这个是分享页面,其他的还有好多页面,比如设置,列表。所有右边弹出的view大小都一样。

可以写一个公用的背景,在那个背景上做进入和退出的动作。这里就要用到 runtimeclass_addMethod了。

直接上代码:

NS_ASSUME_NONNULL_BEGIN

@protocol LiveBroadsideViewProtocol 

///从右边弹出的view 有默认的实现
@optional
- (void)moveIn;
- (void)moveOut:(dispatch_block_t)completeBlock;
@end

///全屏侧边弹出view
@interface PTVLiveBroadsideView : UIView

///显示View
- (void)showView:(id )view;

@end

NS_ASSUME_NONNULL_END

实现部分

#import "PTVLiveBroadsideView.h"
///通用头文件
#import "PTVMacro.h"

///runtime
#import 

///从右边弹出的view添加默认的实现
void moveIn(id self, SEL _cmd) {
    if (![self isKindOfClass:[UIView class]]) {
        return;
    }
    
    UIView *view = self;
    
    CGRect frame = CGRectMake(SCREEN_WIDTH, 0, 350, SCREEN_HEIGHT);
    view.frame = frame;
    [UIView animateWithDuration:0.25
                     animations:^{
                         CGRect frame1 = CGRectMake(SCREEN_WIDTH - 350, 0, 350, SCREEN_HEIGHT);
                         view.frame = frame1;
                     } completion:^(BOOL finished) {
                         
                     }];
}

///默认的MoveOut 实现
void moveOut(UIView *self, SEL _cmd, dispatch_block_t completeBlock) {
    [UIView animateWithDuration:0.25
                     animations:^{
                         CGRect frame1 = CGRectMake(SCREEN_WIDTH, 0, 350, SCREEN_HEIGHT);
                         self.frame = frame1;
                     } completion:^(BOOL finished) {
                         [self removeFromSuperview];
                         if (completeBlock) {
                             completeBlock();
                         }
                     }];
}


@interface PTVLiveBroadsideView()

///当前显示的子View
@property (nonatomic, weak) UIView *currentView;

@end

@implementation PTVLiveBroadsideView

- (void)showView:(id)view {
    [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [(id)obj moveOut:^{
            
        }];
    }];
    
    UIView *_v = (UIView *)view;
    if (![_v isKindOfClass:[UIView class]]) return;
    
    
    if (![view respondsToSelector:@selector(moveIn)]) {
        BOOL sucess = class_addMethod([view class], @selector(moveIn), (IMP)moveIn, "i@:@");
        if (!sucess) {
            return;
        }
    }
    
    if (_v.superview != self) {
        [self addSubview:_v];
    }
    
    
    [view moveIn];
    
    _currentView = _v;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    
    [super touchesEnded:touches withEvent:event];
    
    UITouch *touch = touches.anyObject;
    CGPoint point = [touch locationInView:self];
    if (CGRectContainsPoint(_currentView.frame, point)) return;
    
    if (![_currentView respondsToSelector:@selector(moveOut:)]) {
        BOOL sucess = class_addMethod([_currentView class], @selector(moveOut:), (IMP)moveOut, "i@:@");
        if (!sucess) {
            [_currentView removeFromSuperview];
            [self removeFromSuperview];
            return;
        }
    }
    
    WeakSelf;
    [(id)_currentView moveOut:^{
        [weakSelf removeFromSuperview];
    }];
    
}

@end

动态添加方法思路是看看新加入的view 有没有实现 moveIn 或moveOut 如果没实现,就动态添加一下:

if (![_currentView respondsToSelector:@selector(moveOut:)]) {
        BOOL sucess = class_addMethod([_currentView class], @selector(moveOut:), (IMP)moveOut, "i@:@");

使用的时候,如下:

    if (!_slideView) {
        PTVLiveBroadsideView *slideView = [PTVLiveBroadsideView new];
        slideView.backgroundColor = [UIColor clearColor];
        _slideView = slideView;
    }
   
    [targetController.view addSubview:_slideView];
    _slideView.frame = targetController.view.bounds;
    
//    PTVCommonShareView *sv = [PTVCommonShareView new];
//    PTVDormancyView *sv = [[PTVDormancyView alloc] initWithViewModel:[PTVDornacyViewModel new]];
    PTVVideoQualityView *sv = [[PTVVideoQualityView alloc] initWithViewModel:[PTVVideoQualityViewModel new]];
//    PTVBarrageOptionView *sv = [[PTVBarrageOptionView alloc] initWithViewModel:[PTVBarrageViewModel new]];
    [_slideView showView:(id)sv];

要弹出的view都不用实现moveInmoveOut 方法,在 showView方法里已经动态添加过了。所以在 调用的使用才会强制转化 骗一下编译器

(id)sv

当然,如果大小不一样,可以扩展LiveBroadsideViewProtocol 协议。

你可能感兴趣的:(iOS runtime 应用场景)