美文网首页
iOS开发小技巧整理(持续更新中)

iOS开发小技巧整理(持续更新中)

作者: CoderXiong | 来源:发表于2017-06-30 16:59 被阅读0次
开发中总有那么些小的细节让我们事半功倍,下面我就列一列,希望帮到你,哈哈。

1、禁止手机睡眠
[UIApplication sharedApplication].idleTimerDisabled = YES;

2、隐藏某行cell

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 如果是你需要隐藏的那一行,返回高度为0
    if(indexPath.row == YouWantToHideRow)
        return 0; 
    return 44;
}
// 然后再你需要隐藏cell的时候调用
[self.tableView beginUpdates];
[self.tableView endUpdates];

3、cocoa pods 出现ERROR: While executing gem ... (Errno::EPERM)
解决办法

4、动画切换window的根控制器

// options是动画选项
[UIView transitionWithView:[UIApplication sharedApplication].keyWindow duration:0.5f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        BOOL oldState = [UIView areAnimationsEnabled];
        [UIView setAnimationsEnabled:NO];
        [UIApplication sharedApplication].keyWindow.rootViewController = [RootViewController new];
        [UIView setAnimationsEnabled:oldState];
 } completion:^(BOOL finished) {
 }];

5、去除数组中重复的对象
NSArray *newArr = [oldArr valueForKeyPath:@"distinctUnionOfObjects.self"];

6、跳进app权限设置

// 跳进app设置
if (UIApplicationOpenSettingsURLString != NULL) {
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    [[UIApplication sharedApplication] openURL:url];
}

7、给一个view截图

UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

8、通知宏

#define NOTIF_ADD(n, f)     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(f) name:n object:nil]
#define NOTIF_POST(n, o)    [[NSNotificationCenter defaultCenter] postNotificationName:n object:o]
#define NOTIF_REMV()        [[NSNotificationCenter defaultCenter] removeObserver:self]

9、获取window

+(UIWindow*)getWindow {
    UIWindow* win = nil; //[UIApplication sharedApplication].keyWindow;
    for (id item in [UIApplication sharedApplication].windows) {
        if ([item class] == [UIWindow class]) {
            if (!((UIWindow*)item).hidden) {
                win = item;
                break;
            }
        }
    }
    return win;
}

10、修改textField的placeholder的字体颜色和字体大小

[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
[textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];

11、获取app缓存大小

- (CGFloat)getCachSize {
    NSUInteger imageCacheSize = [[SDImageCache sharedImageCache] getSize];
    //获取自定义缓存大小
    //用枚举器遍历 一个文件夹的内容
    //1.获取 文件夹枚举器
    NSString *myCachePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
    NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:myCachePath];
    __block NSUInteger count = 0;
    //2.遍历
    for (NSString *fileName in enumerator) {
        NSString *path = [myCachePath stringByAppendingPathComponent:fileName];
        NSDictionary *fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
        count += fileDict.fileSize;//自定义所有缓存大小
    }
    // 得到是字节  转化为M
    CGFloat totalSize = ((CGFloat)imageCacheSize+count)/1024/1024;
    return totalSize;
}

12、清理app缓存

- (void)handleClearView {
    //删除两部分
    //1.删除 sd 图片缓存
    //先清除内存中的图片缓存
    [[SDImageCache sharedImageCache] clearMemory];
    //清除磁盘的缓存
    [[SDImageCache sharedImageCache] clearDisk];
    //2.删除自己缓存
    NSString *myCachePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
    [[NSFileManager defaultManager] removeItemAtPath:myCachePath error:nil];
}

13、获取手机型号

+ (NSString *)getDeviceInfo {
        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:@"iPhone9,1"]) return @"国行、日版、港行iPhone 7";
        if ([platform isEqualToString:@"iPhone9,2"]) return @"港行、国行iPhone 7 Plus";
        if ([platform isEqualToString:@"iPhone9,3"]) return @"美版、台版iPhone 7";
        if ([platform isEqualToString:@"iPhone9,4"]) return @"美版、台版iPhone 7 Plus";
        if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE";
        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;
    }

14、判断图片类型

//通过图片Data数据第一个字节 来获取图片扩展名
- (NSString *)contentTypeForImageData:(NSData *)data
{
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c)
    {
        case 0xFF:
            return @"jpeg";
 
        case 0x89:
            return @"png";
 
        case 0x47:
            return @"gif";
 
        case 0x49:
        case 0x4D:
            return @"tiff";
 
        case 0x52:
        if ([data length] < 12) {
            return nil;
        }
 
        NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
        if ([testString hasPrefix:@"RIFF"]
            && [testString hasSuffix:@"WEBP"])
        {
            return @"webp";
        }
 
        return nil;
    }
 
    return nil;
}

15、获取手机和app信息

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];

// app名称
NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"];
NSLog(@"app名称: %@", app_Name);
// app版本
NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
NSLog(@"app版本: %@", app_Version);
// app build版本
NSString *app_build = [infoDictionary objectForKey:@"CFBundleVersion"];
NSLog(@"app build版本: %@", app_build);
//手机别名: 用户定义的名称
NSString* userPhoneName = [[UIDevice currentDevice] name];
NSLog(@"手机别名: %@", userPhoneName);
//设备名称
NSString* deviceName = [[UIDevice currentDevice] systemName];
NSLog(@"设备名称: %@",deviceName );
//手机系统版本
NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
NSLog(@"手机系统版本: %@", phoneVersion);
//手机型号
NSString* phoneModel = [[UIDevice currentDevice] model];
NSLog(@"手机型号: %@",phoneModel );
//地方型号  (国际化区域名称)
NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];
NSLog(@"国际化区域名称: %@",localPhoneModel );
// 当前应用名称
NSString *appCurName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
NSLog(@"当前应用名称:%@",appCurName);
// 当前应用软件版本  比如:1.0.1
NSString *appCurVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
NSLog(@"当前应用软件版本:%@",appCurVersion);
// 当前应用版本号码   int类型
NSString *appCurVersionNum = [infoDictionary objectForKey:@"CFBundleVersion"];
NSLog(@"当前应用版本号码:%@",appCurVersionNum);

16、圆形图片

- (instancetype)circleImage
{
    // 开启图形上下文
    UIGraphicsBeginImageContext(self.size);
    
    // 获得上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // 矩形框
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    
    // 添加一个圆
    CGContextAddEllipseInRect(ctx, rect);
    
    // 裁剪(裁剪成刚才添加的图形形状)
    CGContextClip(ctx);
    
    // 往圆上面画一张图片
    [self drawInRect:rect];
    
    // 获得上下文中的图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 关闭图形上下文
    UIGraphicsEndImageContext();
    return image;
}

17、验证身份证号

- (BOOL)validateIdentityCard {
    BOOL flag;
    if (self.length <= 0) {
        flag = NO;
        return flag;
    }
    NSString *regex2 = @"^(\\d{14}|\\d{17})(\\d|[xX])$";
    NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
    return [identityCardPredicate evaluateWithObject:self];
}

18、给imageView添加倒影

CGRect frame = self.frame;
frame.origin.y += (frame.size.height + 1);

UIImageView *reflectionImageView = [[UIImageView alloc] initWithFrame:frame];
self.clipsToBounds = TRUE;
reflectionImageView.contentMode = self.contentMode;
[reflectionImageView setImage:self.image];
reflectionImageView.transform = CGAffineTransformMakeScale(1.0, -1.0);

CALayer *reflectionLayer = [reflectionImageView layer];

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.bounds = reflectionLayer.bounds;
gradientLayer.position = CGPointMake(reflectionLayer.bounds.size.width / 2, reflectionLayer.bounds.size.height * 0.5);
gradientLayer.colors = [NSArray arrayWithObjects:
                        (id)[[UIColor clearColor] CGColor],
                        (id)[[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3] CGColor], nil];

gradientLayer.startPoint = CGPointMake(0.5,0.5);
gradientLayer.endPoint = CGPointMake(0.5,1.0);
reflectionLayer.mask = gradientLayer;

[self.superview addSubview:reflectionImageView];

19、让label的文字内容显示在左上/右上/左下/右下/中心顶/中心底部

// 自定义UILabel 重写label的textRectForBounds方法
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
    CGRect rect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
    switch (self.textAlignmentType) {
        case WZBTextAlignmentTypeLeftTop: {
            rect.origin = bounds.origin;
        }
            break;
        case WZBTextAlignmentTypeRightTop: {
            rect.origin = CGPointMake(CGRectGetMaxX(bounds) - rect.size.width, bounds.origin.y);
        }
            break;
        case WZBTextAlignmentTypeLeftBottom: {
            rect.origin = CGPointMake(bounds.origin.x, CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeRightBottom: {
            rect.origin = CGPointMake(CGRectGetMaxX(bounds) - rect.size.width, CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeTopCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / 2, CGRectGetMaxY(bounds) - rect.origin.y);
        }
            break;
        case WZBTextAlignmentTypeBottomCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / 2, CGRectGetMaxY(bounds) - CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeLeft: {
            rect.origin = CGPointMake(0, rect.origin.y);
        }
            break;
        case WZBTextAlignmentTypeRight: {
            rect.origin = CGPointMake(rect.origin.x, 0);
        }
            break;
        case WZBTextAlignmentTypeCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / 2, (CGRectGetHeight(bounds) - CGRectGetHeight(rect)) / 2);
        }
            break;
        default:
            break;
    }
    return rect;
}
- (void)drawTextInRect:(CGRect)rect {
    CGRect textRect = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:textRect];
}

20、移除字符串中的空格和换行

+ (NSString *)removeSpaceAndNewline:(NSString *)str {
    NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
    temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    return temp;
}

//待处理的字符串
NSString *string = @" A B  CD  EFG\n MN\n";
//去除两端空格和回车(注意是两端),处理后的string1 = @"A B  CD  EFG\n MN";
NSString *string1 = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

21、获取视频的第一帧图片

NSURL *url = [NSURL URLWithString:filepath];
AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *generate1 = [[AVAssetImageGenerator alloc] initWithAsset:asset1];
generate1.appliesPreferredTrackTransform = YES;
NSError *err = NULL;
CMTime time = CMTimeMake(1, 2);
CGImageRef oneRef = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err];
UIImage *one = [[UIImage alloc] initWithCGImage:oneRef];
return one;

22、删除UIButton的所有点击事件
[testButton removeTarget:nil action:nil forControlEvents:UIControlEventAllEvents];

23、删除某个view所有的子视图
[[self.view subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

24、layoutSubviews方法什么时候调用?

  • 1.init方法不会调用
  • 2.addSubview方法等时候会调用
  • 3.bounds改变的时候调用
  • 4.scrollView滚动的时候会调用scrollView的layoutSubviews方法(所以不建议在scrollView的layoutSubviews方法中做复杂逻辑)
  • 5.旋转设备的时候调用
  • 6.子视图被移除的时候调用

25、tableViewCell分割线顶到头

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [cell setSeparatorInset:UIEdgeInsetsZero];
    [cell setLayoutMargins:UIEdgeInsetsZero];
    cell.preservesSuperviewLayoutMargins = NO;
}
 
- (void)viewDidLayoutSubviews {
    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    [self.tableView setLayoutMargins:UIEdgeInsetsZero];
}

26、UITextView中打开或禁用复制,剪切,选择,全选等功能

// 继承UITextView重写这个方法
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
// 返回NO为禁用,YES为开启
    // 粘贴
    if (action == @selector(paste:)) return NO;
    // 剪切
    if (action == @selector(cut:)) return NO;
    // 复制
    if (action == @selector(copy:)) return NO;
    // 选择
    if (action == @selector(select:)) return NO;
    // 选中全部
    if (action == @selector(selectAll:)) return NO;
    // 删除
    if (action == @selector(delete:)) return NO;
    // 分享
    if (action == @selector(share)) return NO;
    return [super canPerformAction:action withSender:sender];
}

27、字符串反转

//第一种:
- (NSString *)reverseWordsInString:(NSString *)str
{
    NSMutableString *newString = [[NSMutableString alloc] initWithCapacity:str.length];
    for (NSInteger i = str.length - 1; i >= 0 ; i --)
    {
        unichar ch = [str characterAtIndex:i];
        [newString appendFormat:@"%c", ch];
    }
    return newString;
}

//第二种:
- (NSString*)reverseWordsInString:(NSString*)str
{
    NSMutableString *reverString = [NSMutableString stringWithCapacity:str.length];
    [str enumerateSubstringsInRange:NSMakeRange(0, str.length) options:NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences  usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        [reverString appendString:substring];
    }];
    return reverString;
}

28、手动更改iOS状态栏的颜色

- (void)setStatusBarBackgroundColor:(UIColor *)color
{
    UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
 
    if ([statusBar respondsToSelector:@selector(setBackgroundColor:)])
    {
        statusBar.backgroundColor = color;    
    }
}

29、UIView设置部分圆角(左上,右上,左下,右下)

CGRect rect = view.bounds;
CGSize radio = CGSizeMake(30, 30);//圆角尺寸
UIRectCorner corner = UIRectCornerTopLeft|UIRectCornerTopRight;//这是圆角位置
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corner cornerRadii:radio];
CAShapeLayer *masklayer = [[CAShapeLayer alloc]init];//创建shapelayer
masklayer.frame = view.bounds;
masklayer.path = path.CGPath;//设置路径
view.layer.mask = masklayer;

30、获取到webview的高度
CGFloat height = [[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];

31、UIWebView设置User-Agent

//设置
NSDictionary *dic = @{@"UserAgent":@"your UserAgent"};
[[NSUserDefaults standardUserDefaults] registerDefaults:dic];
//获取
NSString *agent = [self.WebView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];

32、UIWebView里面的图片自适应屏幕(在webView加载完的代理方法里面写)

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *js = @"function imgAutoFit() { \
    var imgs = document.getElementsByTagName('img'); \
    for (var i = 0; i ( imgs.length; ++i) { \
    var img = imgs[i]; \
    img.style.maxWidth = %f; \
    } \
    }";
    
    js = [NSString stringWithFormat:js, [UIScreen mainScreen].bounds.size.width - 20];
    
    [webView stringByEvaluatingJavaScriptFromString:js];
    [webView stringByEvaluatingJavaScriptFromString:@"imgAutoFit()"];
}

33、获取webview的内容高度

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    //通过JS代码获取webview的内容高度
    CGFloat height = [[self.infoWebView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
}

34、快速定位僵尸对象
iOS中把那些已经release但还没完全消失的对象叫做僵尸对象,对已经release的对象再次释放,就会发生异常。虽然自从使用ARC后,由于对象释放产生的异常已经大大变少,但偶尔还会出现。开启僵尸对象模式后,就能快速定位到异常位置。开启方式如下:Product-->Scheme-->Edit Scheme. 勾选Enable Zombie Objects即可。

35、Label加中划线

//方法一:直接赋值富文本
UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 50)];
[self.view addSubview:label];
label.text = @"59.00";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor grayColor];
NSMutableAttributedString *newPrice = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"¥%@",label.text]];
[newPrice addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlinePatternSolid | NSUnderlineStyleSingle) range:NSMakeRange(0, newPrice.length)];
label.attributedText = newPrice;

//方法二:子类化UILabel,重写drawTextInRect方法
- (void)drawTextInRect:(CGRect)rect{
    [super drawTextInRect:rect];
    
    NSDictionary *fontdic = [NSDictionary dictionaryWithObjectsAndKeys:[self font],NSFontAttributeName, nil];
    CGSize size = [[self text] sizeWithAttributes:fontdic];
    
    CGFloat strikeWidth = size.width;
    CGRect lineRect;
    
    if ([self textAlignment] == NSTextAlignmentRight) {
        lineRect = CGRectMake(rect.size.width - strikeWidth, rect.size.height/2, strikeWidth, 1);
    } else if ([self textAlignment] == NSTextAlignmentCenter) {
        lineRect = CGRectMake(rect.size.width/2 - strikeWidth/2, rect.size.height/2, strikeWidth, 1);
    } else {
        lineRect = CGRectMake(0, rect.size.height/2, strikeWidth, 1);
    }
    CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextFillRect(context, lineRect);
}

36、不要离屏渲染画圆角
有很多做圆角的方式,最简单的就是设置label.layer.cornerRadius = 2; label.layer.masksToBounds = YES; 但是这样做 if(label.layer.cornerRadius > 0 && label.layer.masksToBounds = YES)会出现离屏渲染,对于页面中只有少量需要做圆角,不会造成卡顿;但是如果是每个Cell都设置多个圆角,就会使列表滑动起来有明显卡顿。

//第一种--只要边框不要背景色
直接设置cornerRadius,不需要设置masksToBounds = YES,就可以实现圆角功能。
//第二种--同时设置label的backgroundColor时
label.layer.backgroundColor = [UIColor redColor].CGColor;
label.layer.cornerRadius = 2;

37、准确判断 WebView 加载完成
当网页重定向发生时,网址被重定向几次,WebViewDidFinishLoad 就会被调用几次。所以如果你只想在最后加载完成时调用某些代码,可以通过webView.isLoading来判断。当 WebViewDidFinishLoad 时如果 webView.isLoading == YES 那么说明网页可能发生了重定向。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (!webView.isLoading) {
        [self webViewDidFinishLoadCompletely];
    }
}

38、获取webView高度

// 对webView中的scrollView设置KVO
[_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];

// KVO具体实现
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"contentSize"]) {
            // 这两个JS代码都可以计算出webview的高度
            // document.documentElement.scrollHeight
            // document.body.offsetHeight
        [_webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            // 加20像素是为了预留出边缘,这里可以随意
            CGFloat height = [result doubleValue] + 20;
            _webHeight = height;
            _webView.frame = CGRectMake(0, 0, kScreenWidth, height);
        }];
    }
}
// 别忘注销kvo
- (void)dealloc
{
    [_webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
}

39、禁用emoji

- (NSString *)disable_emoji:(NSString *)text
{
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]" options:NSRegularExpressionCaseInsensitive error:nil];
    NSString *modifiedString = [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:@""];
    return modifiedString;
}

40、使用第三方键盘,通知监听事件执行多次的解决方法
偶然发现在使用搜狗第三方键盘时候,有些卡顿。
打断点发现:键盘弹出的时候,UIKeyboardWillShowNotification,这个通知监听的方法居然进了3次,而且监听到的键盘高度居然不一致。
最终的解决方法:

#pragma mark - 键盘通知的方法
-(void)keyboardWillShow:(NSNotification *)notification{

    NSDictionary *keyBordInfo = [notification userInfo];
    DDLog(@"keyBordInfo = %@",keyBordInfo);
    NSValue *value = [keyBordInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyBoardRect = [value CGRectValue];
    float height = keyBoardRect.size.height;
    CGRect beginRect = [[keyBordInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect endRect = [[keyBordInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    DDLog(@"keyBordInfo.height = %f",height);
    // 第三方键盘回调三次问题,监听仅执行最后一次
    if(beginRect.size.height > 0 && (beginRect.origin.y - endRect.origin.y > 0)){

            //do someing

    }
}

41、UIAlertController颜色字号更改

NSMutableAttributedString *attTitle = [[NSMutableAttributedString alloc]initWithString:@"标题1" attributes:@{NSForegroundColorAttributeName:[UIColor blueColor],NSFontAttributeName:[UIFont systemFontOfSize:17]}];
NSMutableAttributedString *attMessage = [[NSMutableAttributedString alloc]initWithString:@"message" attributes:@{NSForegroundColorAttributeName:[UIColor purpleColor],NSFontAttributeName:[UIFont systemFontOfSize:14]}];

UIAlertController *action = [UIAlertController alertControllerWithTitle:@"标题1" message:@"message" preferredStyle:UIAlertControllerStyleActionSheet];
[action setValue:attTitle forKey:@"attributedTitle"];
[action setValue:attMessage forKey:@"attributedMessage"];

UIAlertAction *alert1 = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    [self loadCamera];
}];
[alert1 setValue:[UIColor cyanColor] forKey:@"titleTextColor"];
[action addAction:alert1];

UIAlertAction *alert2 = [UIAlertAction actionWithTitle:@"从相册选择照片" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    [self loadPhotoLibraryPhoto];
}];
[alert2 setValue:[UIColor brownColor] forKey:@"titleTextColor"];
[action addAction:alert2];

UIAlertAction *cancelAlert = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    
}];
[cancelAlert setValue:[UIColor redColor] forKey:@"titleTextColor"];
[action addAction:cancelAlert];
[self presentViewController:action animated:YES completion:nil];

42、UILabel下划线

UILabel *testLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 120, 200, 30)];
testLabel.backgroundColor = [UIColor lightGrayColor];
testLabel.textAlignment = NSTextAlignmentCenter;
NSString *cstrTitle = @"This is an attributed string.下划线";
NSDictionary *attribtDic = @{NSUnderlineStyleAttributeName: [NSNumber numberWithInteger:NSUnderlineStyleSingle]};
NSMutableAttributedString *attribtStr = [[NSMutableAttributedString alloc]initWithString:cstrTitle attributes:attribtDic];
testLabel.attributedText = attribtStr;
[self.view addSubview:testLabel];

43、UITextView中打开或禁用复制,剪切,选择,全选等功能

// 子类化UITextView重写下面方法
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    // 返回NO为禁用,YES为开启
    // 粘贴
    if (action == @selector(paste:)) return NO;
    // 剪切
    if (action == @selector(cut:)) return NO;
    // 复制
    if (action == @selector(copy:)) return NO;
    // 选择
    if (action == @selector(select:)) return NO;
    // 选中全部
    if (action == @selector(selectAll:)) return NO;
    // 删除
    if (action == @selector(delete:)) return NO;
    // 分享
    if (action == @selector(share)) return NO;
    return [super canPerformAction:action withSender:sender];
}

44、view添加虚线边框

CAShapeLayer *border = [CAShapeLayer layer];
border.strokeColor = [UIColor colorWithRed:67/255.0f green:37/255.0f blue:83/255.0f alpha:1].CGColor;
border.fillColor = nil;
border.lineDashPattern = @[@4, @2];
border.path = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
border.frame = view.bounds;
[view.layer addSublayer:border];

45、UIImage和base64互转

- (NSString *)encodeToBase64String:(UIImage *)image {
 return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
 
- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
  NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
  return [UIImage imageWithData:data];
}

46、为什么@property声明(NString,NSArray,NSDictionary)时需要使用copy,使用strong有什么问题

  • 因为NString,NSArray,NSDictionary都有自己对应的子类:NSMutableString,NSMutableArray,NSMutableDictionary,而父类指针可以指向子类对象,使用copy可以让本对象不受外界(子对象)影响,无论给我传入的是一个可变对象还是一个不可变对象,都能保证自身持有的是一个不可变副本。
  • 使用strong时,如果这个属性指向一个可变对象,修改可变对象时,这个属性值也会被修改。

47、app新功能半透明蒙层引导

  • mask属性按照我的理解就是显示maskLayer与父layer非透明部分的交集,所以中间的没有path的透明部分就不显示了。

  • 代码实现,self就是占整个屏幕的黑色蒙层,这里的bezierPathByReversingPath可以生成反向的path,frame是需要透明显示的位置

UIBezierPath *path = [UIBezierPath bezierPathWithRect:kScreen_BOUNDS];
[path appendPath: [[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:4] bezierPathByReversingPath]];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
self.layer.mask = shapeLayer;

48、UILabel显示不同颜色字体和行间距

NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:label.text];
//行间距
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:20];
[attrString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, label.text.length)];
//不同颜色
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];
label.attributedText = attrString;

49、防止离屏渲染为image添加圆角

// image分类
-(UIImage *)circleImage
{
    // NO代表透明
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 1);
    // 获得上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 添加一个圆
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    // 方形变圆形
    CGContextAddEllipseInRect(ctx, rect);
    // 裁剪
    CGContextClip(ctx);
    // 将图片画上去
    [self drawInRect:rect];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

50、判断一个字符串是否为数字

NSString *testString = @"123wo";
NSCharacterSet *notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([testString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
    // 是数字
} else
{
    // 不是数字
}

51、获取当前导航控制器下前一个控制器

-(UIViewController *)backViewController
{
    NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];
 
    if ( myIndex != 0 && myIndex != NSNotFound ) {
        return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
    } else {
        return nil;
    }
}

52、让导航控制器pop回指定的控制器

NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *subVC in allViewControllers) {
    if ([subVC isKindOfClass:[CommunityViewController class]]) {
        [self.navigationController popToViewController:subVC animated:NO];
    }
}

53、UIWebView添加单击手势不响应

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(webViewClick)];
tap.delegate = self;
[self.webView addGestureRecognizer:tap];
//因为webView本身有一个单击手势,所以再添加会造成手势冲突,从而不响应。需要绑定手势代理,遵循UIGestureRecognizerDelegate并实现下边的代理方法
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

54、设置UITextField光标位置

//index要设置的光标位置
-(void)cursorLocation:(UITextField *)textField index:(NSInteger)index
{
    NSRange range = NSMakeRange(index, 0);
    UITextPosition *start = [textField positionFromPosition:[textField beginningOfDocument] offset:range.location];
    UITextPosition *end = [textField positionFromPosition:start offset:range.length];
    [textField setSelectedTextRange:[textField textRangeFromPosition:start toPosition:end]];
}

55、去除webView黑底

[webView setBackgroundColor:[UIColor clearColor]];
[webView setOpaque:NO];
for (UIView *subView in [webView subviews])
{
    if ([subView isKindOfClass:[UIScrollView class]])
    {
        for (UIView *v2 in subView.subviews)
        {
            if ([v2 isKindOfClass:[UIImageView class]])
            {
                v2.hidden = YES;
            }
        }
    }
}

56、解决openUrl延时问题

//方法一
dispatch_async(dispatch_get_main_queue(), ^{
     UIApplication *application = [UIApplication sharedApplication];
    if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
        [application openURL:URL options:@{}
           completionHandler:nil];
    } else {
        [application openURL:URL];
    }
});
// 方法二
[self performSelector:@selector(redirectToURL:) withObject:url afterDelay:0.1];
-(void)redirectToURL
{
    UIApplication *application = [UIApplication sharedApplication];
    if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
        [application openURL:URL options:@{}
           completionHandler:nil];
    } else {
        [application openURL:URL];
    }
}

57、获取字符串中的数字

-(NSString *)getNumberFromStr:(NSString *)str
{
    NSCharacterSet *nonDigitCharacterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
    return [[str componentsSeparatedByCharactersInSet:nonDigitCharacterSet] componentsJoinedByString:@""];
}

58、某个界面多个事件同时响应引起的问题

// UIView有个属性叫做exclusiveTouch,设置为YES后,其响应事件会和其他view互斥(有其他view事件响应的时候点击它不起作用)
view.exclusiveTouch = YES;
//一个一个设置太麻烦了,可以全局设置
[[UIView appearance] setExclusiveTouch:YES];
//或者只设置button
[[UIButton appearance] setExclusiveTouch:YES];

59、有的时候一个控制器做为过渡使用,用过之后 push 到下一个页面则不再使用此控制器,如 A -> B -> C, B 是过渡使用的,push 到 C 后即需要将 B 移除出导航栈,以达到可以从 C 直接返回到 A 的目的,其实现依赖 UINavigatioinController 的 setViewControllers: 属性,其实现和使用如下:

//使用分类实现,将自身移除出导航栈
@implementation UIViewController (RemoveFromNavigationStack)
-(void)br_removeFromNavigationControllerStack {
    NSMutableArray *newArray = [self.navigationController.viewControllers mutableCopy];
    [newArray removeObject:self];
    [self.navigationController setViewControllers:newArray animated:YES];
}
@end
//B控制器的实际调用场景
-(void)clickToPushToControllerC:(id)sender {
        ControllerC *vc = [[ControllerC alloc] init];
        [self.navigationController pushToViewController:vc animated:YES];
        [self br_removeFromNavigationControllerStack];
}

60、获取图片扩展名

//通过图片Data数据第一个字节 来获取图片扩展名
- (NSString *)contentTypeForImageData:(NSData *)data {
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return @"jpeg";
        case 0x89:
            return @"png";     
        case 0x47:
            return @"gif";        
        case 0x49:   
        case 0x4D:
            return @"tiff";        
        case 0x52:  
            if ([data length] < 12) {
                return nil;
            }
            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                return @"webp";
            }
            return nil;
    }
    return nil;
}

61、一般使用SDWebImage 进行图片的显示和缓存,一般缓存的内容比较多了就需要进行清空缓存;清除SDWebImage的内存和硬盘时,可以同时清除session 和 cookie的缓存

// 清理内存
[[SDImageCache sharedImageCache] clearMemory];

// 清理webview 缓存
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [storage cookies]) {
    [storage deleteCookie:cookie];
}

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
[config.URLCache removeAllCachedResponses];
[[NSURLCache sharedURLCache] removeAllCachedResponses];

// 清理硬盘
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
    [MBProgressHUD hideAllHUDsForView:self.view animated:YES];

    [self.tableView reloadData];
}];

62、UILongPressGestureRecognizer执行2次的问题

//会调用2次,开始时和结束时
- (void)hello:(UILongPressGestureRecognizer *)longPress
{
    if (longPress.state == UIGestureRecognizerStateEnded)//需要添加一个判断
    {
        NSLog(@"long");

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"hello"

                                                        message:@"Long Press"

                                                       delegate:self

                                              cancelButtonTitle:@"OK"

                                              otherButtonTitles:nil, nil];

        [alert show];
    }
}

63、UITextField 只能输入数字和字母

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textFieldChanged:)
                                                 name:UITextFieldTextDidChangeNotification
                                               object:nil];
监听name:UITextFieldTextDidChangeNotification 和  - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 来实现。
- (BOOL)validatePasswordString:(NSString *)resultMStr
{
    BOOL result = YES;
    switch (self.mode) {
        case HXSChangePasswordLogin: {
            NSString *regex = @"^[a-zA-Z0-9]+$";
            NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
            result = [pred evaluateWithObject:resultMStr];
            break;
        }

        case HXSChangePasswordPay: {
            NSString *regex = @"^[0-9]+$";
            NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
            result = [pred evaluateWithObject:resultMStr];
            break;
        }
    }

    return result;
}

64、NSArray 快速求总和、平均值、最大值、最小值

NSArray *array = [NSArray arrayWithObjects:@"2.0", @"2.3", @"3.0", @"4.0", @"10", nil];
CGFloat sum = [[array valueForKeyPath:@"@sum.floatValue"] floatValue];
CGFloat avg = [[array valueForKeyPath:@"@avg.floatValue"] floatValue];
CGFloat max =[[array valueForKeyPath:@"@max.floatValue"] floatValue];
CGFloat min =[[array valueForKeyPath:@"@min.floatValue"] floatValue];
NSLog(@"总和=%f\n平均值=%f\n最大值=%f\n最小值=%f",sum,avg,max,min);

65、退出app

- (void)exitApplication{
    AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
    UIWindow *window = app.window;
    
    [UIView animateWithDuration:0.5f animations:^{
        window.alpha = 0;
        window.frame = CGRectMake(0, window.bounds.size.width, 0, 0);
    } completion:^(BOOL finished) {
        exit(0);
    }];
}

66、返回当前星期几

- (NSString*)toWeekString
{
    static NSCalendar *calendar;
    if (calendar == nil) {
        calendar =
        [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    }
    
    unsigned unitFlags = NSWeekdayCalendarUnit;
    
    NSDateComponents *comps = [calendar components:unitFlags fromDate:self];
    NSArray *weekArr =
    [NSArray arrayWithObjects:@"日",@"一",@"二",@"三",@"四",@"五",@"六", nil];
    
    return [NSString stringWithFormat:@"星期%@",
            [weekArr objectAtIndex:[comps weekday]-1]];
}

67、把tableview里编辑状态下的cell的勾选的颜色改成别的颜色

self.myTableView.tintColor = [UIColor redColor];

68、iOS Whose view is not in the window hierarchy...

在 一个 ViewController 里面调用另外一个 ViewController
该错误一般是由于在 viewDidLoad 里面调用引起的,解决办法是转移到 viewDidAppear。

69、

相关文章

网友评论

      本文标题:iOS开发小技巧整理(持续更新中)

      本文链接:https://www.haomeiwen.com/subject/cfibcxtx.html