• iOS----runtime 运行时机制03--(设置tabbarButton的badgeView)


    1、获取类身上的成员变量--class_copyIvarList

    if ([badgeViewChild isKindOfClass:NSClassFromString(@"_UIBadgeBackground")]) {
      //NSLog(@"终于找到你,还好没放弃");
      unsigned int count;//获取完成之后,count的值就代码当前类身上成员变量的个数
                                
      //获取类身上的成员变量
      Ivar *vars = class_copyIvarList(NSClassFromString(@"_UIBadgeBackground"), &count);
      //遍历查看
      for (int i=0; i<count; i++) {
          Ivar var = vars[i];
                                    
          //获取var的名字
          NSString *name = [NSString stringWithCString:ivar_getName(var) encoding:NSUTF8StringEncoding];
          //获取类型
          NSString *type = [NSString stringWithCString:ivar_getTypeEncoding(var) encoding:NSUTF8StringEncoding];
                                    
          NSLog(@"%@=====%@",name,type);
                                          if ([name isEqualToString:@"_image"]) {
              //通过kvc赋值
              [badgeViewChild setValue:[UIImage imageNamed:self.badgeImageName] forKeyPath:name];
          }
        }
      //释放内存
      free(vars);
    }

    2、方法交换-->原有的方法调用完之后需要做自己的逻辑

    + (void)load{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class clazz = [self class];
            
            // 获取到原来的方法与需要交互的SEL
            SEL originalSelector = @selector(setBadgeValue:);
            SEL swizzledSelector = @selector(wb_setBadgeValue:);
            
            // 通过SEL 获取到类身上的Method
            Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector);
            
            // 向类身上添加方法
            BOOL result = class_addMethod(clazz, swizzledSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            
            if (result) {
                // 如果添加成功就替换方法实现
                class_replaceMethod(clazz, originalSelector, method_getImplementation(swizzledlMethod), method_getTypeEncoding(swizzledMethod));
            }else{
                // 没有添加成功,直接交换方法实现
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        });
    }

    3、对象关联-->给任何NSObject对象设置一个关联对象-->解决分类里面添加新的属性的get与set方法 (给分类添加属性的方法)

    // 设置关联属性
    - (void)setBadgeImageName:(NSString *)badgeImageName{
        objc_setAssociatedObject(self, @"haha", badgeImageName, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)badgeImageName{
        return objc_getAssociatedObject(self, @"haha");
    }

    // 修改系统显示的badgeValue的显示

    实现:给UITabBarItem添加分类(BadgeValueImage)

    具体实现如下:

    UITabBarItem.h
    //
    //  UITabBarItem+BadgeValueImage.h//
    //  Created by ji on 15/8/20.
    //  Copyright (c) 2015年 ji. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface UITabBarItem (BadgeValueImage)
    @property (nonatomic,copy) NSString *badgeImageName;
    @end
    UITabBarItem.m
    //
    //  UITabBarItem+BadgeValueImage.m//
    //  Created by ji on 15/8/20.
    //  Copyright (c) 2015年 ji. All rights reserved.
    //
    
    #import "UITabBarItem+BadgeValueImage.h"
    #import <objc/runtime.h>
    
    @implementation UITabBarItem (BadgeValueImage)
    
    + (void)load{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class clazz = [self class];
            
            // 获取到原来的方法与需要交互的SEL
            SEL originalSelector = @selector(setBadgeValue:);
            SEL swizzledSelector = @selector(wb_setBadgeValue:);
            
            // 通过SEL 获取到类身上的Method
            Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector);
            
            // 向类身上添加方法
            BOOL result = class_addMethod(clazz, swizzledSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            
            if (result) {
                // 如果添加成功就替换方法实现
                class_replaceMethod(clazz, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            }else{
                // 没有添加成功,直接交换方法实现
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        });
    }
    
    - (void)wb_setBadgeValue:(NSString *)badgeValue{
        //调用父类
        [self wb_setBadgeValue:badgeValue];
        
        // 实现逻辑
        // 如果badgeValue为nil 的话。直接返回
        if(!badgeValue){
            return;
        }
        
        // 我们直接能够拿到的就是WBTabBar
        UITabBarController *target = [self valueForKeyPath:@"_target"];
        
        for (UIView *tabBarChild in target.tabBar.subviews) {
            //找UITabBarButton
            if ([tabBarChild isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
                for (UIView *tabBarButtonChild in tabBarChild.subviews) {
                    if ([tabBarButtonChild isKindOfClass:NSClassFromString(@"_UIBadgeView")]) {
                        for (UIView *badgeViewChild in tabBarButtonChild.subviews) {
                            if ([badgeViewChild isKindOfClass:NSClassFromString(@"_UIBadgeBackground")]) {
                                //NSLog(@"终于找到你,还好没放弃");
                                unsigned int count;//获取完成之后,count的值就代码当前类身上成员变量的个数
                                
                                //获取类身上的成员变量
                                Ivar *vars = class_copyIvarList(NSClassFromString(@"_UIBadgeBackground"), &count);
                                //遍历查看
                                for (int i=0; i<count; i++) {
                                    Ivar var = vars[i];
                                    
                                    //获取var的名字
                                    NSString *name = [NSString stringWithCString:ivar_getName(var) encoding:NSUTF8StringEncoding];
                                    //获取类型
                                    NSString *type = [NSString stringWithCString:ivar_getTypeEncoding(var) encoding:NSUTF8StringEncoding];
                                    
                                    NSLog(@"%@=====%@",name,type);
                                    //
                                    if ([name isEqualToString:@"_image"]) {
                                        //通过kvc赋值
                                        [badgeViewChild setValue:[UIImage imageNamed:self.badgeImageName] forKeyPath:name];
                                    }
                                }
                                //释放内存
                                free(vars);
                            }
                        }
                    }
                }
            }
        }
    }
    
    // 设置关联属性
    - (void)setBadgeImageName:(NSString *)badgeImageName{
        objc_setAssociatedObject(self, @"haha", badgeImageName, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)badgeImageName{
        return objc_getAssociatedObject(self, @"haha");
    }
    
    @end
  • 相关阅读:
    asp.net利用多线程执行长时间的任务,在客户端显示进度条
    电脑不能正常关机的原因和解决方法
    任务栏有两个相同的图标
    输入法不在桌面显示如何解决解决
    ASP操作XML文件的主要方法和实现
    Java开发工具下载
    感人至深的文章
    Java开发工具下载地址
    网页上图片用ps写上字之后边上锯齿严重
    队列中取最大值操作问题
  • 原文地址:https://www.cnblogs.com/jiqiaochun/p/4745431.html
Copyright © 2020-2023  润新知