判断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;
}
|
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是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]];
});
}
|
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];
}
|
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;
|
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: 圆角)
OC: IB_DESIGNABLE 和 IBInspectable ``` // .h @property (nonatomic, assign) IBInspectable CGFloat cornerRadius;
// .m IB_DESIGNABLE @implementation KLButton
方法不确定的参数 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;
|
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)];
|