iOS一些小功能记录

2018-12-27  本文已影响38人  临川慕容吹雪

从网上看到和平时用到一些iOS代码小功能记录下,方便后续查阅

----------------------------持续更新------------------------

1.UIView截图
- (UIImage *)getImageWithView:(UIView *)view {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);

   //获取当前上下文
   CGContextRef ctx = UIGraphicsGetCurrentContext();
  //渲染
   [view.layer renderInContext:ctx];
   UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();
   return newImage;
}
//生成UIView形式的View
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
2.UIView设置阴影
  //设置阴影颜色
    self.testView.layer.shadowColor = [UIColor blueColor].CGColor;
    //设置阴影透明度
    self.testView.layer.shadowOpacity = 0.8;
    //阴影圆角
    self.testView.layer.shadowRadius = 1;
    //设置阴影偏离位置
    self.testView.layer.shadowOffset = CGSizeMake(10, 2);
    
    UIEdgeInsets edges = UIEdgeInsetsMake(8, 10, 0, 0);
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(edges.left, edges.top, CGRectGetWidth(self.testView2.frame), CGRectGetHeight(self.testView2.frame))];
    //通过 shadowPath 设置阴影,可以自定义阴影的形状,这个方式可以避免离屏渲染
    self.testView2.layer.shadowPath = path.CGPath;
    self.testView2.layer.shadowColor = [UIColor blueColor].CGColor;
    //设置阴影透明度
    self.testView2.layer.shadowOpacity = 0.8;
    //阴影圆角
   self.testView2.layer.shadowRadius = 1;
3.设置圆角
//给某个角度设置圆角 同样会触发离屏幕渲染
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.testView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)];
 CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
 maskLayer.frame = self.testView.bounds;
 maskLayer.path = maskPath.CGPath;
 self.testView.layer.mask = maskLayer;
 //四个角设置圆角
 CAShapeLayer *mask = [CAShapeLayer new];
 mask.path = [UIBezierPath bezierPathWithRoundedRect:self.testView2.bounds cornerRadius:10].CGPath;
self.testView2.layer.mask = mask;

详细参考iOS设置圆角的四种方法

4.查看打印类的私有方法
UIView *view = [[UIView alloc] init];
NSLog(@"_ivarDescription%@", [view  performSelector:@selector(_ivarDescription)]);
NSLog(@"_methodDescription =%@", [view performSelector:@selector(_methodDescription)]);
NSLog(@"_shortMethodDescription =%@", [view performSelector:@selector(_shortMethodDescription)]);

结果如图:


_ivarDescription
_shortMethodDescription

参考:
Extended Type Info in Objective-C
三个打印类信息的私有方法
Powerful private methods for debugging in Cycript & LLDB

5.iOS 9 以后通知不再需要手动移除
603C343F-CA1C-4C1C-93C7-65A4EDE43EFF.png

参考:
官方文档
iOS 9 以后通知不再需要手动移除

6.判断iPhone异形屏几种方式
  if (@available(iOS 11, *)) {
        UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
        if (keyWindow == nil) {
            keyWindow = [[UIApplication sharedApplication] delegate].window;
        }
        CGFloat bottomSafeInset = keyWindow.safeAreaInsets.bottom;
        //竖屏34 横屏21.f
        if (bottomSafeInset == 34.f || bottomSafeInset == 21.f) {
            NSLog(@"我是异形屏");
        }
    }
//宏定义 判断是否是iPhone异形屏
#define  isIPhoneXSeries()\
^(){\
    BOOL iPhoneXSerie = NO;\
    if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {\
        return iPhoneXSerie;\
    }\
    if (@available(iOS 11.0, *)) {\
        UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];\
        if (mainWindow.safeAreaInsets.bottom > 0.0) {\
            iPhoneXSerie = YES;\
        }\
    }\
    return iPhoneXSerie;\
}()
 CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    if (statusBarHeight == 44.f) {
        NSLog(@"我是异形屏");
    }
   UIUserInterfaceIdiom idiom = [[UIDevice currentDevice] userInterfaceIdiom];
    if (idiom == UIUserInterfaceIdiomPhone) {
        if (@available(iOS 11, *)) {
            LAContext *laContext = [[LAContext alloc] init];
            if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]) {
                if (laContext.biometryType == LABiometryTypeFaceID) {
                    NSLog(@"我是异形屏");
                }
            }
        }
    }
7.iOS9 以后字符串转换API

- (nullable NSString *)stringByApplyingTransform:(NSStringTransform)transform reverse:(BOOL)reverse API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));
支持拼音繁体简体等转换。

    NSString *stringTest = @"我是一个测试";
    NSString * changeIntoPinYin = [stringTest stringByApplyingTransform:NSStringTransformToLatin reverse:NO];
    NSLog(@"汉字转拼音= %@",changeIntoPinYin);
    //去掉结合符号
    NSLog(@"去掉结合符号 = %@",[changeIntoPinYin stringByApplyingTransform:NSStringTransformStripCombiningMarks reverse:NO]);
    NSLog(@"简体转繁体= %@",[stringTest  stringByApplyingTransform:@"Hans-Hant" reverse:NO]);
打印结果

可参考
ICU Text Transforms in Foundation
Cocoa中的ICU文本转换
ICU - International Components for Unicode

8.为了防止遍历等其他的操作的时候内存压力过大,导致崩溃异常,可手动控制这些对象的生命周期,在适当的位置加上@autoreleasepool{}
9.使用runtime动态创建类

举个例子我这里创建一个继承FitfunBaseService的类。

#import <objc/runtime.h>

NSString * offlineApiBaseUrl(id self,SEL _cmd1){
    return objc_getAssociatedObject([self class], "apiServiceBaseUrl");
}


void createServiceClass(NSString *className,NSString *baseUrl) {
    const char * myClassName;
    myClassName = [className UTF8String];
    Class pClass = NSClassFromString(className);
    if (NSClassFromString(className) || NSClassFromString(@"FitfunBaseService") == nil) {
        return;
    }
    
    //创建类
    pClass = objc_allocateClassPair(NSClassFromString(@"FitfunBaseService"), myClassName, 0);
    objc_setAssociatedObject(pClass, "apiServiceBaseUrl", baseUrl, OBJC_ASSOCIATION_COPY);
    //为类创建方法
   class_addMethod(pClass, @selector(offlineApiBaseUrl), (IMP)offlineApiBaseUrl, "@@:");
    //注册类,使其能被引用。
    objc_registerClassPair(pClass);
}
10.runtime交换方法
void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector) {
   
    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 swizzleMethodDifferentClasses(Class originalClass,Class swizzledClass, SEL originalSelector, SEL swizzledSelector) {
    //类方法交换
    Method originalMethod = class_getClassMethod(originalClass, originalSelector);
    Method swizzledMethod = class_getClassMethod(swizzledClass, swizzledSelector);
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

11.除去数组重复元素

NSArray *oldArray = @[@"1",@"3",@"1",@{@"1":@"2"},@{@"1":@"2"},@{@"1":@"3"}];
NSArray *newArray = [oldArray valueForKeyPath:@"@distinctUnionOfObjects.self"];
NSLog(@"oldArray =%@,newArray =%@",oldArray, newArray);
//输出结果
oldArray =(
    1,
    3,
    1,
        {
        1 = 2;
    },
        {
        1 = 2;
    },
        {
        1 = 3;
    }
),newArray =(
    1,
    3
)

关于数组更多的kvc用法可参考高效开发iOS -- 那些不为人知的KVC

12.修改textField的placeholder的字体颜色、大小
[textField setValue:[UIColor greenColor] forKeyPath:@"_placeholderLabel.textColor"];
[textField setValue:[UIFont boldSystemFontOfSize:15] forKeyPath:@"_placeholderLabel.font"];
<==>等价
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:
placeholder attributes:
@{NSFontAttributeName : [UIFont systemFontOfSize:15],
NSForegroundColorAttributeName : [UIColor  greenColor]}];
13.环境变量 DYLD_PRINT_STATISTICS打印出程序启动过程中各个阶段所消耗的时间,DYLD_PRINT_LIBRARIES (启动前和启动后的)和 DYLD_PRINT_LIBRARIES_POST_LAUNCH(启动后的),打印 dyld 加载的库

强调:DYLD_PRINT_STATISTICS 变量打印时间是iOS10以后才支持的功能,所以需要用iOS10系统及以上的机器来做测试。

配置环境变量
控制台打印结果
强烈推荐看iOS启动时间优化 ,讲的非常不错
14.更容易看懂宏

对于宏定义,可以使用xcode自带对单个文件预处理功能
Produce -> Perform Action -> Preprocess 'xxxx.m'

xcode操作
预处理后 预处理后
15.获取UIImage 图片的一部分
 UIImage *image = [UIImage imageNamed:@"test.png"];
 CGImageRef imageRef = image.CGImage;
 //这里xy和宽高相对于图片原始坐标来说来说的,比如我的图片现在宽高941x719,他的原始坐标就是(0,0,941,719)
 //取从图片从坐标(16,110)开始宽高都是290的局部
 CGRect imageRect = CGRectMake(160, 110, 290, 290);
 CGImageRef imageRectRef = CGImageCreateWithImageInRect(imageRef, imageRect);
 UIImage *newImage = [[UIImage alloc] initWithCGImage:imageRectRef];
 self.testImageView.image = newImage;
16.给UIView设置image
 UIImage *image = [UIImage imageNamed:@"test.png"];
 CGImageRef imageRef = image.CGImage;
 self.testView.layer.contents = (__bridge id)imageRef;
//设置拉伸范围
 self.testView.layer.contentsCenter = CGRectMake(0.8, 0.8, 1, 1);
上一篇下一篇

猜你喜欢

热点阅读