随记

1、圆角、方角的优化设置

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *myView;
@property (nonatomic, strong) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 200, 300)];
    self.imageView.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.imageView];
    self.imageView.image = [UIImage imageNamed:@"美图.jpg"];
    
    
    self.myView = [[UIView alloc] initWithFrame:CGRectMake(50, 400, 100, 50)];
    self.myView.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.myView];
    
    
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(200, 400, 100, 50)];
    self.label.backgroundColor = [UIColor brownColor];
    [self.view addSubview:self.label];
    
//    [self test1];
//    [self test2];
//    [self test3];
    
    [self test5];
    [self test6];
}
- (void)test1
{
    // 对于UIView来说,设置圆角就用下面这行代码就可以了,不会带来任何性能损耗
    self.myView.layer.cornerRadius = 10;
}

- (void)test2
{
    // 对于UIImageView、UILabel这些内部还有子视图的控件来说,用下面的代码可以设置圆角,但会带来性能损耗
    // 设置masksToBounds会导致离屏渲染,从而影响性能;屏幕上这样设置的圆角视图很多时,就会很卡,影响用户体验
    // ios9.0之后对UIImageView的圆角设置做了优化,UIImageView这样设置圆角不会触发离屏渲染,ios9.0之前还是会触发离屏渲染。而UIButton都会触发离屏渲染。
    self.imageView.layer.masksToBounds = YES;
    self.imageView.layer.cornerRadius = 10;
    
    self.label.layer.masksToBounds = YES;
    self.label.layer.cornerRadius = 10;
}

- (void)test3
{
    // shouldRasterize=YES设置光栅化,可以使离屏渲染的结果缓存到内存中存为位图,使用的时候直接使用缓存,节省了一直离屏渲染损耗的性能。但是如果layer及sublayers常常改变的话,它就会一直不停的渲染及删除缓存重新创建缓存,所以这种情况下建议不要使用光栅化,这样也是比较损耗性能的。
    self.imageView.layer.masksToBounds = YES;
    self.imageView.layer.cornerRadius = 10;
    self.imageView.layer.shouldRasterize = YES;
    
    self.label.layer.masksToBounds = YES;
    self.label.layer.cornerRadius = 10;
    self.label.layer.shouldRasterize = YES;
}

- (void)test4
{
    // 下面这种方法本质上是用遮罩层mask来实现,因此同样无可避免的会导致离屏渲染。当圆角视图很多时,也会很卡。
    // 而且我们应该尽量避免重写drawRect方法,不恰当的使用这个方法会导致内存暴增。举个例子,iPhone6 上与屏幕等大的UIView,即使重写一个空的drawRect方法,它也至少占用750*1134*4字节≈3.4MB的内存。在“内存恶鬼drawRect”(http://bihongbo.com/2016/01/03/memoryGhostdrawRect)及其后续中,作者详细介绍了其中原理,据他测试,在iPhone6上空的、与屏幕等大的视图重写drawRect方法会消耗5.2MB内存。总之,能避免重写 drawRect方法就尽可能避免。
    UIBezierPath *bezierPath1 = [UIBezierPath bezierPathWithRoundedRect:self.myView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 10)];
    CAShapeLayer *maskLayer1 = [CAShapeLayer layer];
    maskLayer1.frame = self.myView.bounds;
    maskLayer1.path = bezierPath1.CGPath;
    self.myView.layer.mask = maskLayer1;
    
    
    UIBezierPath *bezierPath2 = [UIBezierPath bezierPathWithRoundedRect:self.imageView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft cornerRadii:CGSizeMake(10, 10)];
    CAShapeLayer *maskLayer2 = [CAShapeLayer layer];
    maskLayer2.frame = self.imageView.bounds;
    maskLayer2.path = bezierPath2.CGPath;
    self.imageView.layer.mask = maskLayer2;
    
    
    UIBezierPath *bezierPath3 = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(10, 10)];
    CAShapeLayer *maskLayer3 = [CAShapeLayer layer];
    maskLayer3.frame = self.label.bounds;
    maskLayer3.path = bezierPath3.CGPath;
    self.label.layer.mask = maskLayer3;
}

// 为UIView设置圆角
// 这种是手动画出圆角。虽然我们之前说过,为普通的视图直接设置 cornerRadius属性即可。但万一不可避免的需要使用masksToBounds,就可以使用下面这种方法
// 这个方法返回的是UIImage,也就是说我们利用Core Graphics自己画出了一个圆角矩形。除了一些必要的代码外,最核心的就是 CGContextAddArcToPoint函数。它中间的四个参数表示曲线的起点和终点坐标,最后一个参数表示半径。调用了四次函数后,就可以画出圆角矩形。最后再从当前的绘图上下文中获取图片并返回。有了这个图片后,我们创建一个UIImageView并插入到视图层级的底部:
- (void)test5
{
    CGFloat borderWidth = 0;
    CGFloat halfBorderWidth = borderWidth / 2.0;
    
    UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, [[UIScreen mainScreen] scale]);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    
    CGContextSetLineWidth(context, borderWidth);
    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
    
    CGFloat width = self.myView.bounds.size.width;
    CGFloat height = self.myView.bounds.size.height;
    CGFloat radius = 10;
    // 右边开始
    CGContextMoveToPoint(context, width - halfBorderWidth, radius + halfBorderWidth);
    // 右下角角度
    CGContextAddArcToPoint(context, width - halfBorderWidth, height - halfBorderWidth, width - radius - halfBorderWidth, height - halfBorderWidth, radius);
    // 左下角角度
    CGContextAddArcToPoint(context, halfBorderWidth, height - halfBorderWidth, halfBorderWidth, height - radius - halfBorderWidth, radius);
    // 左上角
    CGContextAddArcToPoint(context, halfBorderWidth, halfBorderWidth, width - halfBorderWidth, halfBorderWidth, radius);
    // 右上角
    CGContextAddArcToPoint(context, width - halfBorderWidth, halfBorderWidth, width - halfBorderWidth, radius + halfBorderWidth, radius);
    
    CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [self.myView insertSubview:[[UIImageView alloc] initWithImage:image] atIndex:0];
}
// 为UIImageView添加圆角
- (void)test6
{
    UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, [[UIScreen mainScreen] scale]);
    CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithRoundedRect:self.imageView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(30, 30)].CGPath);
    CGContextClip(UIGraphicsGetCurrentContext());
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor yellowColor].CGColor);
    [self.imageView.image drawInRect:self.imageView.bounds];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    self.imageView.image = image;
}
/*
 使用方法5或方法6,需要小心使用背景色。因为我们没有设置masksToBounds,因此超出圆角的部分依然会被显示。因此,你不应该再使用背景颜色,可以在绘制圆角矩形时设置填充颜色来达到类似效果。
 方法6中,在为UIImageView添加圆角时,请确保image属性不是nil,否则这个设置将会无效。
*/

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end
demo截图

效果

2、添加自定义的字体

  • 字体有相应的字体文件,一般以ttf或者otf为后缀,我们可以去一些第三方网站去下载,也可以自己做字体打包好。
  • 准备好之后就把xx.ttf字体库文件加到工程里。
  • 然后在工程的plist文件中添加Fonts provided by application项,并设置相应的ttf文件进去,这样就告诉了应用,我要加入新的字体了,对应的字体文件是哪些。


    添加字库文件
  • 那么工程里就可以直接使用这个字体了
    NSString *textStr = @"测试字体12345678Jiajia①②③④⑤";
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 74, [UIScreen mainScreen].bounds.size.width - 20, 40)];
    label.text = textStr;
    label.font = [UIFont fontWithName:@"AvenirNextCondensed-BoldItalic" size:24];
    [self.view addSubview:label1];
  • 如果不知道字体名称,可以遍历字体进行查询
for (NSString *fontFamilyName in [UIFont familyNames])
{
      NSLog(@"fontFamilyName:=========%@", fontFamilyName);
      for (NSString *fontName in [UIFont fontNamesForFamilyName:fontFamilyName])
      {
           NSLog(@"fontName:==========%@", fontName);
      }
      NSLog(@"*********************************************");
}
遍历查询字体名
效果

3、cocoapods路径:/Users/用户名/.cocoapods

4、判断手机型号、系统版本、电池电量

#import "ViewController.h"

#import <sys/utsname.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 手机类型
    NSLog(@"型号:%@", [self iphoneType]);
    
    // 手机系统名
    NSLog(@"手机系统名:%@", [[UIDevice currentDevice] systemName]);
    
    // 手机系统版本号
    NSLog(@"手机系统版本号:%@", [[UIDevice currentDevice] systemVersion]);
    
    // 电池电量
    // 此方法不精确
    // 返回的是0 .. 1.0 .. -1.0之间的浮点值,另外-1.0表示模拟器
    [UIDevice currentDevice].batteryMonitoringEnabled = YES;
    CGFloat batteryLevel = [[UIDevice currentDevice] batteryLevel];
    NSLog(@"电池电量:%.0f%%",100.0 * batteryLevel);
}
// 精确获取电量的方法:http://www.jianshu.com/p/11c1afdf5415

- (NSString *)iphoneType
{
    struct utsname systemInfo;
    
    uname(&systemInfo);
    
    NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
    
    if ([platform isEqualToString:@"iPhone1,1"])
        return @"iPhone 2G";
    
    if ([platform isEqualToString:@"iPhone1,2"])
        return @"iPhone 3G";
    
    if ([platform isEqualToString:@"iPhone2,1"])
        return @"iPhone 3GS";
    
    if ([platform isEqualToString:@"iPhone3,1"])
        return @"iPhone 4";
    
    if ([platform isEqualToString:@"iPhone3,2"])
        return @"iPhone 4";
    
    if ([platform isEqualToString:@"iPhone3,3"])
        return @"iPhone 4";
    
    if ([platform isEqualToString:@"iPhone4,1"])
        return @"iPhone 4S";
    
    if ([platform isEqualToString:@"iPhone5,1"])
        return @"iPhone 5";
    
    if ([platform isEqualToString:@"iPhone5,2"])
        return @"iPhone 5";
    
    if ([platform isEqualToString:@"iPhone5,3"])
        return @"iPhone 5c";
    
    if ([platform isEqualToString:@"iPhone5,4"])
        return @"iPhone 5c";
    
    if ([platform isEqualToString:@"iPhone6,1"])
        return @"iPhone 5s";
    
    if ([platform isEqualToString:@"iPhone6,2"])
        return @"iPhone 5s";
    
    if ([platform isEqualToString:@"iPhone7,1"])
        return @"iPhone 6 Plus";
    
    if ([platform isEqualToString:@"iPhone7,2"])
        return @"iPhone 6";
    
    if ([platform isEqualToString:@"iPhone8,1"])
        return @"iPhone 6s";
    
    if ([platform isEqualToString:@"iPhone8,2"])
        return @"iPhone 6s Plus";
    
    if ([platform isEqualToString:@"iPod1,1"])
        return @"iPod Touch 1G";
    
    if ([platform isEqualToString:@"iPod2,1"])
        return @"iPod Touch 2G";
    
    if ([platform isEqualToString:@"iPod3,1"])
        return @"iPod Touch 3G";
    
    if ([platform isEqualToString:@"iPod4,1"])
        return @"iPod Touch 4G";
    
    if ([platform isEqualToString:@"iPod5,1"])
        return @"iPod Touch 5G";
    
    if ([platform isEqualToString:@"iPad1,1"])
        return @"iPad 1G";
    
    if ([platform isEqualToString:@"iPad2,1"])
        return @"iPad 2";
    
    if ([platform isEqualToString:@"iPad2,2"])
        return @"iPad 2";
    
    if ([platform isEqualToString:@"iPad2,3"])
        return @"iPad 2";
    
    if ([platform isEqualToString:@"iPad2,4"])
        return @"iPad 2";
    
    if ([platform isEqualToString:@"iPad2,5"])
        return @"iPad Mini 1G";
    
    if ([platform isEqualToString:@"iPad2,6"])
        return @"iPad Mini 1G";
    
    if ([platform isEqualToString:@"iPad2,7"])
        return @"iPad Mini 1G";
    
    if ([platform isEqualToString:@"iPad3,1"])
        return @"iPad 3";
    
    if ([platform isEqualToString:@"iPad3,2"])
        return @"iPad 3";
    
    if ([platform isEqualToString:@"iPad3,3"])
        return @"iPad 3";
    
    if ([platform isEqualToString:@"iPad3,4"])
        return @"iPad 4";
    
    if ([platform isEqualToString:@"iPad3,5"])
        return @"iPad 4";
    
    if ([platform isEqualToString:@"iPad3,6"])
        return @"iPad 4";
    
    if ([platform isEqualToString:@"iPad4,1"])
        return @"iPad Air";
    
    if ([platform isEqualToString:@"iPad4,2"])
        return @"iPad Air";
    
    if ([platform isEqualToString:@"iPad4,3"])
        return @"iPad Air";
    
    if ([platform isEqualToString:@"iPad4,4"])
        return @"iPad Mini 2G";
    
    if ([platform isEqualToString:@"iPad4,5"])
        return @"iPad Mini 2G";
    
    if ([platform isEqualToString:@"iPad4,6"])
        return @"iPad Mini 2G";
    
    if ([platform isEqualToString:@"i386"])
        return @"iPhone Simulator";
    
    if ([platform isEqualToString:@"x86_64"])
        return @"iPhone Simulator";
    
    return platform;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

5、在动画中动态改变约束

创建一个ViewController,勾选xib选项。在xib文件里拖一个label,水平、垂直居中,宽高均为100


label

选中label高度的约束,拖动到viewController.m文件中成为属性,在UIview animation方法中修改约束

#import "MyViewController.h"

@interface MyViewController ()

@property (weak, nonatomic) IBOutlet UILabel *myLabel;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *myLabel_height;

@end

@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [UIView animateWithDuration:3 animations:^{
        
        self.myLabel_height.constant = 300;
        [self.view layoutIfNeeded];
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

修改约束时需要调用layoutIfNeeded方法


动态改变约束.gif

6、根据十六进制颜色参数设置颜色

颜色
#import <UIKit/UIKit.h>

@interface UIColor (Extension)

+(UIColor *)colorWithHexString:(NSString *)str;

@end
#import "UIColor+Extension.h"

@implementation UIColor (Extension)

+(UIColor *)colorWithHexString:(NSString *)str
{
    // stringByTrimmingCharactersInSet:方法用来去除字符串前后两端的特殊符号
    // whitespaceAndNewlineCharacterSet指空格和回车
    NSString *cSrting = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    // 也可以自定义一个NSCharacterSet,里面包含需要去除的符号
//    NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@")#<,>:;"];
    if (cSrting.length != 7)
    {
        return nil;
    }
    
    unsigned red, green, blue;
    NSRange range;
    
    range.location = 1;
    range.length = 2;
    [[NSScanner scannerWithString:[cSrting substringWithRange:range]] scanHexInt:&red];
    
    range.location = 3;
    [[NSScanner scannerWithString:[cSrting substringWithRange:range]] scanHexInt:&green];
    
    range.location = 5;
    [[NSScanner scannerWithString:[cSrting substringWithRange:range]] scanHexInt:&blue];
    
    UIColor *color= [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1];
    
    return color;
}

@end
#import "ViewController.h"

#import "UIColor+Extension.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor colorWithHexString:@"#1ccfa0"];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

7、给文件添加访问权限

一次在运行一个工程时发现报错了:Permission Denied,就是一个文件拒绝访问,没有访问权限
解决办法:

  • 打开终端,进入文件所在的目录
  • 输入命令:chmod 755 Pods-shuziweiba-frameworks.sh,回车(Pods-shuziweiba-frameworks.sh是文件名)


    命令
  • 重新运行工程

推荐阅读更多精彩内容