ios app一键设置全局公祭模式(灰色模式)

随着国家越来越多的公祭纪念活动,我们的app被要求在特定的时间全部灰色化,以配合国家公祭活动。悼念革命烈士,人民英雄。
经过多方查找资料研究,发现一个相对简单的方法。
首先引入以下Category文件,到项目中


47B71BC2-C6FF-4704-BFA8-26DF72D67F17.png
引入之后把头文件引入到AppDelegate中, 然乎在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中写以下几个方法即可实现灰色
#import "AppDelegate.h"

#import "UIColor+LhGray.h"
#import "UIImage+GrayImage.h"
#import "UIImageView+GrayImageview.h"
#import "UITabBarItem+LhGray.h"
#import "WKWebView+LhGray.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    //设置灰色模式
    [UITabBarItem lh_tabbarItemSwizzldMethedWith:YES];
    [UIColor lh_colorSwizzldColorMethedWith:YES];
    [UIImage lh_imageSwizzldMethedWith:YES];
    [UIImageView lh_imageViewSwizzldMethedWith:YES];
    [WKWebView lh_WKWebViewWizzldMethedWith:YES];
    return YES;
}

我只发.m文件

这个是颜色文件的分类

#import "UIColor+LhGray.h"
#import 

@implementation UIColor (LhGray)

+(void)lh_colorSwizzldColorMethedWith:(BOOL)changeGray{
    
    Class cls = object_getClass(self);
    
    //将系统提供的colorWithRed:green:blue:alpha:替换掉
    Method originMethod = class_getClassMethod(cls, @selector(colorWithRed:green:blue:alpha:));
    Method swizzledMethod = class_getClassMethod(cls, @selector(lg_colorWithRed:green:blue:alpha:));
    [self swizzleMethodWithOriginSel:@selector(colorWithRed:green:blue:alpha:) oriMethod:originMethod swizzledSel:@selector(lg_colorWithRed:green:blue:alpha:) swizzledMethod:swizzledMethod class:cls];
    
    //将系统提供的colors也替换掉
    NSArray *array = [NSArray arrayWithObjects:@"redColor",@"greenColor",@"blueColor",@"cyanColor",@"yellowColor",@"magentaColor",@"orangeColor",@"purpleColor",@"brownColor",@"systemBlueColor",@"systemGreenColor", nil];
    
    for (int i = 0; i < array.count ; i ++) {
        SEL sel = NSSelectorFromString(array[i]);
        SEL lg_sel = NSSelectorFromString([NSString stringWithFormat:@"lg_%@",array[i]]);
        Method originMethod = class_getClassMethod(cls, sel);
        Method swizzledMethod = class_getClassMethod(cls, lg_sel);
        [self swizzleMethodWithOriginSel:sel oriMethod:originMethod swizzledSel:lg_sel swizzledMethod:swizzledMethod class:cls];
    }
}

+ (void)swizzleMethodWithOriginSel:(SEL)oriSel
                         oriMethod:(Method)oriMethod
                       swizzledSel:(SEL)swizzledSel
                    swizzledMethod:(Method)swizzledMethod
                             class:(Class)cls {
    BOOL didAddMethod = class_addMethod(cls, oriSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(cls, swizzledSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
    } else {
        method_exchangeImplementations(oriMethod, swizzledMethod);
    }
}

+ (UIColor *)lg_redColor {
    // 1.0, 0.0, 0.0 RGB
    UIColor *color = [self lg_redColor];
    color = [self changeGrayWithColor:color Red:1.0 green:0.0 blue:0.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_greenColor {
     // 0.0, 1.0, 0.0 RGB
    UIColor *color = [self lg_greenColor];
    color = [self changeGrayWithColor:color Red:0.0 green:1.0 blue:0.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_blueColor {
    //0.0, 0.0, 1.0
    UIColor *color = [self lg_blueColor];
    color = [self changeGrayWithColor:color Red:0.0 green:0.0 blue:1.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_cyanColor {
    // 0.0, 1.0, 1.0
    UIColor *color = [self lg_cyanColor];
    color = [self changeGrayWithColor:color Red:0.0 green:1.0 blue:1.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_yellowColor {
    //1.0, 1.0, 0.0
    UIColor *color = [self lg_yellowColor];
    color = [self changeGrayWithColor:color Red:1.0 green:1.0 blue:0.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_magentaColor {
    // 1.0, 0.0, 1.0
    UIColor *color = [self lg_magentaColor];
    color = [self changeGrayWithColor:color Red:1.0 green:0.0 blue:1.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_orangeColor {
    // 1.0, 0.5, 0.0
    UIColor *color = [self lg_orangeColor];
    color = [self changeGrayWithColor:color Red:1.0 green:0.5 blue:0.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_systemBlueColor {
    UIColor *color = [self lg_systemBlueColor];
    color = [self changeGrayWithColor:color Red:0.0 green:0.0 blue:1.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_systemGreenColor {
    UIColor *color = [self lg_systemGreenColor];
    color = [self changeGrayWithColor:color Red:0.0 green:1.0 blue:0.0 alpha:1.0];
    return color;
}

+ (UIColor *)lg_purpleColor {
    // 0.5, 0.0, 0.5
    UIColor *color = [self lg_purpleColor];
    color = [self changeGrayWithColor:color Red:0.5 green:0.0 blue:0.5 alpha:1.0];
    return color;
}

+ (UIColor *)lg_brownColor {
    // 0.6, 0.4, 0.2
    UIColor *color = [self lg_brownColor];
    color = [self changeGrayWithColor:color Red:0.6 green:0.4 blue:0.2 alpha:1.0];
    return color;
}

+ (instancetype)lg_colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a {
    
    UIColor *color = [self lg_colorWithRed:r green:g blue:b alpha:a];
    if (r == 0 && g == 0 && b == 0) {
        return color;
    }
    color = [self changeGrayWithColor:color Red:r green:g blue:b alpha:a];
    return  color;
}

+ (UIColor *)changeGrayWithColor:(UIColor *)color Red:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a {
    CGFloat gray = r * 0.299 +g * 0.587 + b * 0.114;
    UIColor *grayColor = [UIColor colorWithWhite:gray alpha:a];
    return  grayColor;
}
@end

这个是image文件的分类

#import "UIImage+GrayImage.h"
@implementation UIImage (GrayImage)

+(void)lh_imageSwizzldMethedWith:(BOOL)changeGray{
    
    if (changeGray == false) {
        return;
    }
    //交换方法
    Class cls = object_getClass(self);
    Method originMethod = class_getClassMethod(cls, @selector(imageNamed:));
    Method swizzledMethod = class_getClassMethod(cls, @selector(lg_imageNamed:));
    
    [self swizzleMethodWithOriginSel:@selector(imageNamed:) oriMethod:originMethod swizzledSel:@selector(lg_imageNamed:) swizzledMethod:swizzledMethod class:cls];
    
    Method originMethod1 = class_getClassMethod(cls, @selector(imageWithData:));
    Method swizzledMethod1 = class_getClassMethod(cls, @selector(lg_imageWithData:));
    [self swizzleMethodWithOriginSel:@selector(imageWithData:) oriMethod:originMethod1 swizzledSel:@selector(lg_imageWithData:) swizzledMethod:swizzledMethod1 class:cls];
    
}

+ (void)swizzleMethodWithOriginSel:(SEL)oriSel
                         oriMethod:(Method)oriMethod
                       swizzledSel:(SEL)swizzledSel
                    swizzledMethod:(Method)swizzledMethod
                             class:(Class)cls {
    BOOL didAddMethod = class_addMethod(cls, oriSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(cls, swizzledSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
    } else {
        method_exchangeImplementations(oriMethod, swizzledMethod);
    }
}

+ (UIImage *)lg_imageWithData:(NSData *)data {
    UIImage *image = [self lg_imageWithData:data];
    return [image grayImage];
}

+ (UIImage *)lg_imageNamed:(NSString *)name {
    UIImage *image = [self lg_imageNamed:name];
    return [image grayImage];
}

// 转化灰度
- (UIImage *)grayImage {
    const int RED =1;
    const int GREEN =2;
    const int BLUE =3;

    // Create image rectangle with current image width/height
    CGRect imageRect = CGRectMake(0,0, self.size.width* self.scale, self.size.height* self.scale);

    int width = imageRect.size.width;
    int height = imageRect.size.height;

    // the pixels will be painted to this array
    uint32_t *pixels = (uint32_t*) malloc(width * height *sizeof(uint32_t));

    // clear the pixels so any transparency is preserved
    memset(pixels,0, width * height *sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // create a context with RGBA pixels
    CGContextRef context = CGBitmapContextCreate(pixels, width, height,8, width *sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

    // paint the bitmap to our context which will fill in the pixels array
    CGContextDrawImage(context,CGRectMake(0,0, width, height), [self CGImage]);

    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];

            // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
            uint32_t gray = 0.3 * rgbaPixel[RED] +0.59 * rgbaPixel[GREEN] +0.11 * rgbaPixel[BLUE];

            // set the pixels to gray
            rgbaPixel[RED] = gray;
            rgbaPixel[GREEN] = gray;
            rgbaPixel[BLUE] = gray;
        }
    }

    // create a new CGImageRef from our context with the modified pixels
    CGImageRef imageRef = CGBitmapContextCreateImage(context);

    // we're done with the context, color space, and pixels
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);

    // make a new UIImage to return
    UIImage *resultUIImage = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:UIImageOrientationUp];

    // we're done with image now too
    CGImageRelease(imageRef);

    return resultUIImage;
}

这个是UIImageView分类

#import "UIImageView+GrayImageview.h"
#import "UIImage+GrayImage.h"
#import 

@implementation UIImageView (GrayImageview)

+(void)lh_imageViewSwizzldMethedWith:(BOOL)changeGray;{
    
    if (changeGray == false) {
        return;
    }
    
    Class class = [self class];
    
    SEL originalSelector = @selector(setImage:);
    SEL swizzledSelector = @selector(swizzled_setImage:);
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}


- (void)swizzled_setImage:(UIImage *)image {
    //系统键盘处理(如果不过滤,这系统键盘字母背景是黑色)
    if ([self.superview isKindOfClass:NSClassFromString(@"UIKBSplitImageView")]) {
        [self swizzled_setImage:image];
        return;
    }
    UIImage *im = [[image grayImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
//    UIImage *im = [image grayImage];
    [self swizzled_setImage:im];
}

@end

这个是UITabBarItem分类

#import "UITabBarItem+LhGray.h"
#import 

@implementation UITabBarItem (LhGray)
+ (void)lh_tabbarItemSwizzldMethedWith:(BOOL)changeGray{
    if (changeGray == false) {
        return;
    }
    Class cls = [self class];
    
    SEL oriSel = @selector(setSelectedImage:);
    SEL swizzldSel = @selector(lh_setTabbarItemImage:);
    
    Method originMethed = class_getInstanceMethod(cls, oriSel);
    Method swizzldMethed = class_getInstanceMethod(cls, swizzldSel);
    
    BOOL isAddMethed = class_addMethod(cls, oriSel, method_getImplementation(swizzldMethed),method_getTypeEncoding(swizzldMethed));
    if (isAddMethed) {
        class_replaceMethod(cls, swizzldSel, method_getImplementation(originMethed), method_getTypeEncoding(originMethed));
    }else{
        method_exchangeImplementations(originMethed,swizzldMethed);
    }
}
- (void)lh_setTabbarItemImage:(UIImage *)image {
    UIImage *im = [[self imageToTransparent:image] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    [self lh_setTabbarItemImage:im];
}

- (UIImage*)imageToTransparent:(UIImage*) image
{
    // 分配内存
    const int imageWidth = image.size.width;
    const int imageHeight = image.size.height;
    size_t bytesPerRow = imageWidth * 4;
    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);

    // 创建context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);

    // 遍历像素
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    for (int i = 0; i < pixelNum; i++, pCurPtr++)
    {
        uint8_t* ptr = (uint8_t*)pCurPtr;
        if (ptr[3] < 50 && ptr[3] < 50 && ptr[1] < 50) {
            ptr[0] = 0;
        } else {
// 灰度算法
            uint8_t gray = ptr[3] * 0.299 + ptr[2] * 0.587 + ptr[1] * 0.114;
            ptr[3] = gray; //0~255
            ptr[2] = gray;
            ptr[1] = gray;
        }
    }

    // 将内存转成image
    CGDataProviderRef dataProvider =CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData);

    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight,8, 32, bytesPerRow, colorSpace,
                                        kCGImageAlphaLast |kCGBitmapByteOrder32Little, dataProvider,
                                        NULL, true,kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);

    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];

    // 释放
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    return resultUIImage;
}

void ProviderReleaseData (void *info, const void *data, size_t size)
{
    free((void*)data);
}

@end

这个是WKWebView分类

#import "WKWebView+LhGray.h"
#import 
//#import "SCConst.h"

@implementation WKWebView (LhGray)

+(void)lh_WKWebViewWizzldMethedWith:(BOOL)changeGray{
    if (changeGray == false) {
        return;
    }
    
    Method originalMethod = class_getInstanceMethod([self class], @selector(initWithFrame:configuration:));
    Method swizzledMethod = class_getInstanceMethod([self class], @selector(lg_initWithFrame:configuration:));
    method_exchangeImplementations(originalMethod, swizzledMethod);
}


- (instancetype)lg_initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration {
    // js脚本
    NSString *jScript = @"var filter = '-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%); -ms-filter:grayscale(100%); -o-filter:grayscale(100%) filter:grayscale(100%);';document.getElementsByTagName('html')[0].style.filter = 'grayscale(100%)';";
    // 注入
    WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
                 
    WKUserContentController *userController = [[WKUserContentController alloc] init];
    [userController addUserScript:wkUScript];
    
    // 配置对象
    WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
    wkWebConfig.userContentController = userController;
    configuration = wkWebConfig;
    WKWebView *webView = [self lg_initWithFrame:frame configuration:configuration];
    return webView;
}


@end

参考文献 https://www.jianshu.com/p/7b74cebe26a6

你可能感兴趣的:(ios app一键设置全局公祭模式(灰色模式))