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

 

posted @ 2015-08-20 15:55  十点听风  阅读(270)  评论(0编辑  收藏  举报