文章

iOS技巧

判断iPhoneX++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static inline BOOL isIPhoneXSeries() {
    BOOL iPhoneXSeries = NO;
    if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {
        return iPhoneXSeries;
    }

    if (@available(iOS 11.0, *)) {
        UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
        if (mainWindow.safeAreaInsets.bottom > 0.0) {
            iPhoneXSeries = YES;
        }
    }

    return iPhoneXSeries;
}

Button 大小

1
2
3
4
5
- (CGSize)intrinsicContentSize {
    CGSize originalSize = [super intrinsicContentSize];
    CGSize size = CGSizeMake(originalSize.width+10, originalSize.height);
    return size;
}

截屏

1
2
3
4
5
6
7
8
- (UIImage *)screenshot {
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    UIGraphicsBeginImageContextWithOptions(window.bounds.size, YES, [UIScreen mainScreen].scale);
    [window.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

设置pageControl单页不显示

1
self.pageControl.hidesForSinglePage = YES;

让数组中的所有对象都执行一下方法

1
[self.view.subViews makeObjectsPerformSelector:@selecter(removeFromSuperView)];

scrollsToTop

scrollsToTop是UIScrollView的一个属性,主要用于点击设备的状态栏时,是scrollsToTop == YES的控件滚动返回至顶部。每一个默认的UIScrollView的实例,他的scrollsToTop属性默认为YES,所以要实现某一UIScrollView的实例点击设备状态栏返回顶部,则需要关闭其他的UIScrollView的实例的scrollsToTop属性为NO。

SB跳转

1
2
3
4
5
6
7
8
9
10
// 跳转
[self performSegueWithIdentifier:@"login2Contact" sender:nil];
// 在执行跳转之前的时候调用
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    UIViewController *vc = segue.destinationViewController;
    vc.title = [NSString stringWithFormat:@"%@的联系人列表", _accountField.text];
    NSLog(@"%@--%@",segue.sourceViewController,segue.destinationViewController);
}

iOS 10拨打系统电话发现弹出框会延迟2s左右

解决方案一:

1
2
3
4
5
6
7
8
9
10
11
12
13
+ (void)callPhone:(NSString *)phoneNum {
    if (phoneNum.length == 0) {
        return;
    }
    NSString *callPhone = [NSString stringWithFormat:@"telprompt://%@", phoneNum];
    NSComparisonResult compare = [[UIDevice currentDevice].systemVersion compare:@"10.0"];
    if (compare == NSOrderedDescending || compare == NSOrderedSame) {
        /// 大于等于10.0系统使用此openURL方法
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone] options:@{} completionHandler:nil];
    } else {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone]];
    }
}

解决方案二:

1
2
3
4
5
6
7
8
9
+ (void)callPhone:(NSString *)phoneNum {
    if (phoneNum.length == 0) {
        return;
    }
    NSString *callPhone = [NSString stringWithFormat:@"telprompt://%@", phoneNum];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callPhone]];
    });
}

修改TableViewHeaderView字体大小

1
2
3
4
5
6
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
    header.textLabel.textColor = [UIColor grayColor];
    header.textLabel.font = [UIFont systemFontOfSize:15];
    header.contentView.backgroundColor = [UIColor groupTableViewBackgroundColor];
}

heightForHeaderInSection设置高度无效

1
2
3
4
iOS11默认开启Self-Sizing,关闭Self-Sizing即可。
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;

屏蔽一些无知的警告

Xcode8里边 Edit Scheme-> Run -> Arguments, 在Environment Variables里边添加 OS_ACTIVITY_MODE = Disable · 如果写了之后还是打印log,请重新勾选对勾,就可以解决了。

UITableView收起键盘

1
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

长按复制功能

1
2
3
4
5
6
7
8
9
- (void)viewDidLoad {
    [self.view addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pasteBoard:)]];
}
- (void)pasteBoard:(UILongPressGestureRecognizer *)longPress {
    if (longPress.state == UIGestureRecognizerStateBegan) {
        UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
        pasteboard.string = @"需要复制的文本";
    }
}

禁止手机睡眠

1
[UIApplication sharedApplication].idleTimerDisabled = YES;

禁用button高亮

1
2
3
button.adjustsImageWhenHighlighted = NO;
或者在创建的时候
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

控制屏幕旋转,在控制器中写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** 是否支持自动转屏 */
- (BOOL)shouldAutorotate {
    return YES;
}

/** 支持哪些屏幕方向 */
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

/** 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法) */
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}

获取app缓存大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 继承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];
}

禁止textField和textView的复制粘贴菜单

1
2
3
4
5
6
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    if ([UIMenuController sharedMenuController]) {
        [UIMenuController sharedMenuController].menuVisible = NO;
    }
    return NO;
}

为一个view添加虚线边框

1
2
3
4
5
6
7
 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];

设置tableView分割线颜色

1
[self.tableView setSeparatorColor:[UIColor myColor]];

UIImage和base64互转

1
2
3
4
5
6
7
8
- (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];
}

摇一摇功能

1
2
3
4
5
6
7
8
9
10
11
1、打开摇一摇功能
[UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
2、让需要摇动的控制器成为第一响应者
[self becomeFirstResponder];
3、实现以下方法
// 开始摇动
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
// 取消摇动
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
// 摇动结束
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event

发起QQ聊天

QQ开通推广服务以接收陌生消息

1
2
3
4
5
6
7
8
//是否安装QQ
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"mqq://"]]) {
    //用来接收临时消息的客服QQ号码(注意此QQ号需开通QQ推广功能,否则陌生人向他发送消息会失败)         
    NSString *QQ = @"1099779883";         
    //调用QQ客户端,发起QQ临时会话         
    NSString *url = [NSString stringWithFormat:@"mqq://im/chat?chat_type=wpa&uin=%@&version=1&src_type=web",QQ];         
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}

MJRefresh

webview去掉长按后的选择和复制菜单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1. webview 执行 js
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {

    NSLog(@"%s", __FUNCTION__);
    // 禁用选中效果
    [self.webView evaluateJavaScript:@"document.documentElement.style.webkitUserSelect='none'" completionHandler:nil];
    [self.webView evaluateJavaScript:@"document.documentElement.style.webkitTouchCallout='none'" completionHandler:nil];

}

func webViewDidFinishLoad(webView: UIWebView) {
    //禁用webview长按后文字选择框和放大框
    webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitUserSelect='none'")
    webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitTouchCallout='none'")
  }

2. 或者前端写css
<style type="text/css">
*:not(input,textarea) {
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>

XIB 可见属性设置(eg: 圆角)

  1. OC: IB_DESIGNABLEIBInspectable ``` // .h @property (nonatomic, assign) IBInspectable CGFloat cornerRadius;

// .m IB_DESIGNABLE @implementation KLButton

  • (void)setCornerRadius:(CGFloat)cornerRadius { self.layer.cornerRadius = cornerRadius; self.layer.masksToBounds = (cornerRadius > 0); }

  • (CGFloat)cornerRadius { return self.layer.cornerRadius; } ```

    1. Swift: IBInspectableIBDesignable

方法不确定的参数 va_arg 宏的使用

当我们方法需要传入多个不确定的参数时(如:[NSArray arrayWithObjects]), 我们可以使用 ,… 的形式表示,当要取传入的参数的值时就需要用到 va_arg 宏去取。 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)viewDidLoad {
    [super viewDidLoad];
    [self testMethod:@"123",@"456",@"789",nil];
}


- (void)testMethod:(NSString *)test,.. NS_REQUIRES_NIL_TERMINATION {
    va_list argList;
    va_start(argList, test);
    {
        for (id params = test; params != nil; params = va_arg(argList, id)){

            NSLog(@"id = %@---class = %@",params,NSStringFromClass([params class]));
        }
    }
    va_end(argList);
}

去除数组中重复的对象

1
NSArray *newArr = [oldArr valueForKeyPath:@"@distinctUnionOfObjects.self"];

删除NSUserDefaults所有记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//方法一
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
//方法二
- (void)resetDefaults {
  NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
    NSDictionary * dict = [defs dictionaryRepresentation];
    for (id key in dict) {
        [defs removeObjectForKey:key];
    }
    [defs synchronize];
 }
// 方法三
[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];

UITableViewCell 分割线置顶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
    [self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 10, 0, 0)];
}

if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
    [self.tableView setLayoutMargins:UIEdgeInsetsMake(0, 10, 0, 0)];
}
// 3. cell 下
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
    [cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
    [cell setLayoutMargins:UIEdgeInsetsZero];
}

设置UIViewController的view的top在navigationBar下面 & bottom位置在Tabbar的上面

1
2
tabBarController.tabBar.translucent = NO;
uiviewController.navigationController.navigationBar.translucent = NO;

禁用button高亮,点击变灰的效果

1
2
3
button.adjustsImageWhenHighlighted = NO;
或者在创建的时候
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

自定义cell选中背景颜色

1
2
3
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];

UILabel设置内边距

1
2
3
4
5
6
子类化UILabel,重写drawTextInRect方法
- (void)drawTextInRect:(CGRect)rect {
    // 边距,上左下右
    UIEdgeInsets insets = {0, 5, 0, 5};
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}

UILabel设置文字描边

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
子类化UILabel,重写drawTextInRect方法
- (void)drawTextInRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();
    // 设置描边宽度
    CGContextSetLineWidth(c, 1);
    CGContextSetLineJoin(c, kCGLineJoinRound);
    CGContextSetTextDrawingMode(c, kCGTextStroke);
    // 描边颜色
    self.textColor = [UIColor redColor];
    [super drawTextInRect:rect];
    // 文本颜色
    self.textColor = [UIColor yellowColor];
    CGContextSetTextDrawingMode(c, kCGTextFill);
    [super drawTextInRect:rect];
}

改变UISlider的进度条高度

需要继承UISlider并t重载trackRectForBounds方法

1
2
3
- (CGRect)trackRectForBounds:(CGRect)bounds {
    return CGRectMake(0, 0, CGRectGetWidth(self.frame), 5.0);
}

iOS 11中隐藏section头尾的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 0.1f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 0.1f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return nil;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    return nil;
}

更改UITabBar && UINavigationBar背景颜色

1
2
[[UITabBar appearance] setBarTintColor:[UIColor redColor]];
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];

更改UITabBar && UINavigationBar字体颜色

1
2
3
4
5
6
7
//改变按钮navigationBar tintColor颜色
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:102/255.0 green:102/255.0 blue:102/255.0 alpha:1.0];
//改变tabbar 正常颜色,选中色
NSDictionary *attributeNormal = @{NSForegroundColorAttributeName:[UIColor grayColor]};
[subVC.tabBarItem setTitleTextAttributes:attributeNormal forState:(UIControlStateNormal)];
NSDictionary *attributeSelected = @{NSForegroundColorAttributeName:[UIColor redColor]};
[subVC.tabBarItem setTitleTextAttributes:attributeSelected forState: (UIControlStateSelected)];
本文由作者按照 CC BY 4.0 进行授权