本文主要记录日常工作中积累的一些 iOS 小技巧
SDWebImage 加载大量高清图片时内存暴增
解决方案: 关闭 SD 加载高清大图时的解压缩
- static BOOL SDImageCacheOldShouldDecompressImages = YES;
- static BOOL SDImagedownloderOldShouldDecompressImages = YES;
- - (void)viewDidLoad {
- [super viewDidLoad];
- // 关闭 SD 加载高清大图时的解压缩
- SDImageCache *canche = [SDImageCache sharedImageCache];
- SDImageCacheOldShouldDecompressImages = canche.shouldDecompressImages;
- canche.shouldDecompressImages = NO;
- SDWebImageDownloader *downloder = [SDWebImageDownloader sharedDownloader];
- SDImagedownloderOldShouldDecompressImages = downloder.shouldDecompressImages;
- downloder.shouldDecompressImages = NO;
- }
- -(void)dealloc {
- SDImageCache *canche = [SDImageCache sharedImageCache];
- canche.shouldDecompressImages = SDImageCacheOldShouldDecompressImages;
- SDWebImageDownloader *downloder = [SDWebImageDownloader sharedDownloader];
- downloder.shouldDecompressImages = SDImagedownloderOldShouldDecompressImages;
- }
SDWebImage 本地缓存有时候会害人. 如果之前缓存过一张图片, 即使下次服务器换了这张图片, 但是图片 url 没换, 用 SDWebimage 下载下来的还是以前那张, 所以遇到这种问题, 不要先去怼服务器, 清空下缓存再试就好了.
禁止手机睡眠
[UIApplication sharedApplication].idleTimerDisabled = YES;
隐藏某行 cell
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- // 如果是你需要隐藏的那一行, 返回高度为 0
- if(indexPath.row == YouWantToHideRow){
- return 0;
- }
- return 44;
- }
- // 然后再你需要隐藏 cell 的时候调用
- [self.tableView beginUpdates];
- [self.tableView endUpdates];
禁用 button 高亮
button.adjustsImageWhenHighlighted = NO;
或者在创建的时候
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
动画切换 Windows 的根控制器
- [UIView transitionWithView:[UIApplication sharedApplication].keyWindow duration:.5f
- options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
- BOOL oldState = [UIView areAnimationsEnabled];
- [UIView setAnimationsEnabled:NO];
- [UIApplication sharedApplication].keyWindow.rootViewController = [[RootViewController alloc]init];
- [UIView setAnimationsEnabled:oldState];
- } completion:^(BOOL finished) {
- }];
去除数组中重复的对象
NSArray *newArr = [oldArr valueForKeyPath:@"@distinctUnionOfObjects.self"];
编译的时候遇到 no such file or directory: /users/apple/XXX
是因为编译的时候, 在此路径下找不到这个文件, 解决这个问题, 首先是是要检查缺少的文件是不是在工程中, 如果不在工程中, 需要从本地拖进去, 如果发现已经存在工程中了, 或者拖进去还是报错, 这时候需要去 build phases 中搜索这个文件, 这时候很可能会搜出现两个相同的文件, 这时候, 有一个路径是正确的, 删除另外一个即可. 如果删除了还是不行, 需要把两个都删掉, 然后重新往工程里拖进这个文件即可
iOS8 系统中, tableView 最好实现下 - tableView: heightForRowAtIndexPath: 这个代理方法, 要不然在 iOS8 中可能就会出现显示不全或者无法响应事件的问题
iOS8 中实现侧滑功能的时候这个方法必须实现, 要不然在 iOS8 中无法侧滑
- // 必须写的方法, 和 editActionsForRowAtIndexPath 配对使用, 里面什么不写也行
- - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
- }
三个比较特殊的通知
NSSystemTimeZoneDidChangeNotification 监听修改时间界面的两个按钮状态变化
UIApplicationSignificantTimeChangeNotification 监听用户改变时间 (只要点击自动设置按钮就会调用)
NSSystemClockDidChangeNotification 监听用户修改时间 (时间不同才会调用)
获取不到 UICollectionView 指定 cell 的问题
- [self.collectionView layoutIfNeeded];// 添加这句话就好
- QTMResContinueEditeCell *cell = (QTMResContinueEditeCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:_index inSection:0]];
跳进 App 权限设置
- // 跳进 App 设置
- if (UIApplicationOpenSettingsURLString != NULL) {
- UIApplication *application = [UIApplication sharedApplication];
- NSURL *URL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
- if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
- [application openURL:URL options:@{}
- completionHandler:nil];
- } else {
- [application openURL:URL];
- }
- }
给一个 view 截图
- - (UIImage *)cutImageWithView:(UIView *)view
- {
- UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0);
- [view.layer renderInContext:UIGraphicsGetCurrentContext()];
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return image;
- }
注意对象为 nil 的时候, 调用此对象分类的方法不会执行
collectionView 的内容小于其宽高的时候是不能滚动的, 设置可以滚动:
- collectionView.alwaysBounceHorizontal = YES;
- collectionView.alwaysBounceVertical = YES;
颜色转图片
- + (UIImage *)imageWithColor:(UIColor *)color {
- // 描述一个矩形
- CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
- // 开启图形上下文
- UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
- // 获得图形上下文
- CGContextRef ctx = UIGraphicsGetCurrentContext();
- // 使用 color 演示填充上下文
- CGContextSetFillColorWithColor(ctx, [color CGColor]);
- // 渲染上下文
- CGContextFillRect(ctx, rect);
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- // 关闭图形上下文
- UIGraphicsEndImageContext();
- return image;
- }
view 设置圆角
- #define ViewBorderRadius(View, Radius, Width, Color)\
- \
- [View.layer setCornerRadius:(Radius)];\
- [View.layer setMasksToBounds:YES];\
- [View.layer setBorderWidth:(Width)];\
- [View.layer setBorderColor:[Color CGColor]] // view 圆角
view 某个角度设置圆角
- UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.whiteView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)];
- CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
- maskLayer.frame = self.whiteView.bounds;
- maskLayer.path = maskPath.CGPath;
- self.whiteView.layer.mask = maskLayer;
- ## 指定了需要成为圆角的角该参数是 UIRectCorner 类型的, 可选的值有:
- * UIRectCornerTopLeft
- * UIRectCornerTopRight
- * UIRectCornerBottomLeft
- * UIRectCornerBottomRight
- * UIRectCornerAllCorners
由角度转换弧度
#define DegreesToRadian(x) (M_PI * (x) / 180.0)
由弧度转换角度
#define RadianToDegrees(radian) (radian*180.0)/(M_PI)
获取图片资源
- // 建议使用前两种宏定义, 性能高于后者
- #define LOADIMAGE(file,ext) [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:file ofType:ext]]
- #define IMAGE(A) [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:A ofType:nil]]
- #define ImageNamed(_pointer) [UIImage imageNamed:[UIUtil imageName:_pointer]]
- #define UIImageName(name) [UIImage imageNamed:name]
文件路径
- // 获取 temp
- #define PathTemp NSTemporaryDirectory()
- // 获取 Document
- #define PathDocument [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
- // 获取 Cache
- #define PathCache [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]
GCD 代码只执行一次
- #define kDISPATCH_ONCE_BLOCK(onceBlock) static dispatch_once_t onceToken;
- dispatch_once(&onceToken, onceBlock);
自定义 NSLog
- //DEBUG 模式下打印日志, 当前行
- #ifdef DEBUG
- # define DLog(fmt, ...) NSLog((@"%s [Line %d]" fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
- #else
- # define DLog(...)
- #endif
- // 重写 NSLog,Debug 模式下打印日志和当前行数
- #if DEBUG
- #define NSLog(FORMAT, ...) fprintf(stderr,"\nfunction:%s line:%d content:%s\n", __FUNCTION__, __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
- #else
- #define NSLog(FORMAT, ...) nil
- #endif
- //DEBUG 模式下打印日志, 当前行 并弹出一个警告
- #ifdef DEBUG
- # define ULog(fmt, ...) {
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%s\n [Line %d]", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show];
- }
- #else
- # define ULog(...)
- #endif
- Font
- #define FONTS(size) [UIFont systemFontOfSize:(size)]
- #define BOLDFONTS(size) [UIFont boldSystemFontOfSize:(size)]
- GCD
- // 主线程
- #define kDISPATCH_MAIN_THREAD(mainQueueBlock) dispatch_async(dispatch_get_main_queue(), mainQueueBlock);
- // 异步线程
- #define kDISPATCH_GLOBAL_QUEUE_DEFAULT(globalQueueBlock) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), globalQueueBlocl);
通知
- #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]
- Color
- // RGB 颜色转换 (16 进制 ->10 进制)
- #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000)>> 16))/255.0 green:((float)((rgbValue & 0xFF00)>> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
- // 获取 RGB 颜色
- #define RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
- // 清除背景色
- #define CLEARCOLOR [UIColor clearColor]
- // 随机色
- #define RandomCOLOR RGBCOLOR(arc4random_uniform(256),arc4random_uniform(256),arc4random_uniform(256))
获取 Windows
- +(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;
- }
修改 textField 的 placeholder 的字体颜色, 大小
- [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
- [textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];
- // 或者
- textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholder attributes:@{
- NSFontAttributeName : [UIFont systemFontOfSize:13],NSForegroundColorAttributeName : [UIColor grayColor]
- }];
App 缓存
- /** * 存 数组数据 */
- +(void)setObectOfArray:(NSArray *)array fileName:(NSString *)fileName
- {
- // 缓存文件的 根路径
- NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- // 缓存 文件夹 路径
- NSString *filePath = [path stringByAppendingPathComponent:@"XXX.dataCache"];
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:filePath] == NO)
- {
- [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
- }
- // 缓存文件的路径
- NSString * cacheFilePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist",fileName]];
- BOOL isSuccess = [array writeToFile:cacheFilePath atomically:NO];
- if (isSuccess) {
- NSLog(@"缓存数据成功:---%@",cacheFilePath);
- }else
- {
- NSLog(@"缓存数据失败:---%@",cacheFilePath);
- }
- }
- /*** 取 数组数据 */
- +(NSArray *)cacheArrayForFileName:(NSString *)fileName
- {
- // 缓存文件的 根路径
- NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- // 缓存 文件夹 路径
- NSString *filePath = [path stringByAppendingPathComponent:@"XXX.dataCache"];
- // 缓存文件的路径
- NSString * cacheFilePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist",fileName]];
- // 取得缓存文件
- NSArray *array = [NSArray arrayWithContentsOfFile:cacheFilePath];
- return array;
- }
- /*** 清除 这个全部的缓存数据 */
- +(void)clearCacheListData:(void (^)())completion
- {
- // 异线程
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- // 清楚缓存
- // 缓存文件的 根路径
- NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- // 缓存 文件夹 路径
- NSString *filePath = [path stringByAppendingPathComponent:@"FortuneDonkey.dataCache"];
- NSFileManager *manager = [NSFileManager defaultManager];
- // 移除文件夹
- [manager removeItemAtPath:filePath error:nil];
- // 创建一个新的文件夹
- [manager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
- if (completion)
- {
- // 回调主线程
- dispatch_async(dispatch_get_main_queue(), ^{
- completion();
- });
- }
- });
- }
- /*** 清除 SD 缓存数据 */
- -(void)clearSDCacheData
- {
- // 先清除内存中的图片缓存
- [[SDImageCache sharedImageCache] clearMemory];
- // 清除磁盘的缓存
- [[SDImageCache sharedImageCache] clearDisk];
- }
获取 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;
- }
几个常用权限判断
- if ([CLLocationManager authorizationStatus] ==kCLAuthorizationStatusDenied) {
- NSLog(@"没有定位权限");
- }
- AVAuthorizationStatus statusVideo = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
- if (statusVideo == AVAuthorizationStatusDenied) {
- NSLog(@"没有摄像头权限");
- }
- // 是否有麦克风权限
- AVAuthorizationStatus statusAudio = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
- if (statusAudio == AVAuthorizationStatusDenied) {
- NSLog(@"没有录音权限");
- }
- [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
- if (status == PHAuthorizationStatusDenied) {
- NSLog(@"没有相册权限");
- }
- }];
系统相关的一些方法
- // 获取系统版本
- #define IOS_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
- #define IS_IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue]>= 10.0)
- // 获取当前语言
- #define CurrentLanguage ([[NSLocale preferredLanguages] objectAtIndex:0])
- // 判断是否 Retina 屏, 设备是否 %fhone 5, 是否是 iPad
- #define isRetina ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO)
- #define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)
- #define iPhone6 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(750, 1334), [[UIScreen mainScreen] currentMode].size) : NO)
- #define isPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
- // 判断是真机还是模拟器
- #if TARGET_OS_IPHONE
- //iPhone Device
- #endif
- #if TARGET_IPHONE_SIMULATOR
- //iPhone Simulator
- #endif
长按复制功能
- - (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 = @"我是文字";
- }
- }
判断图片类型
- // 通过图片 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;
- }
获取手机和 App 信息
- // 手机序列号
- NSString* identifierNumber = [[UIDevice currentDevice] uniqueIdentifier];
- // 手机别名: 用户定义的名称
- NSString* userPhoneName = [[UIDevice currentDevice] name];
- // 设备名称
- NSString* deviceName = [[UIDevice currentDevice] systemName];
- // 手机系统版本
- NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
- // 手机型号
- NSString* phoneModel = [[UIDevice currentDevice] model];
- // 地方型号 (国际化区域名称)
- NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];
- NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
- // 当前应用名称
- NSString *appCurName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
- // 当前应用版本
- NSString *appCurVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
- // 当前应用版本号码 int 类型
- NSString *appCurVersionNum = [infoDictionary objectForKey:@"CFBundleVersion"];
UIImage 绘制圆角
- - (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;
- }
准确获取图片像素
- CGFloat fixelW = CGImageGetWidth(image.CGImage);
- CGFloat fixelH = CGImageGetHeight(image.CGImage);
JSON 字符串转字典
- + (NSDictionary *)parseJSONStringToNSDictionary:(NSString *)JSONString {
- NSData *JSONData = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
- NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableLeaves error:nil];
- return responseJSON;
- }
获取当前控制器
- // 获取当前屏幕显示的 viewcontroller
- - (UIViewController *)getCurrentVC{
- UIWindow *Windows = [[UIApplication sharedApplication].Windows firstObject];
- if (!Windows) {
- return nil;
- }
- UIView *tempView;
- for (UIView *subview in Windows.subviews) {
- if ([[subview.classForCoder description] isEqualToString:@"UILayoutContainerView"]) {
- tempView = subview;
- break;
- }
- }
- if (!tempView) {
- tempView = [Windows.subviews lastObject];
- }
- id nextResponder = [tempView nextResponder];
- while (![nextResponder isKindOfClass:[UIViewController class]] || [nextResponder isKindOfClass:[UINavigationController class]] || [nextResponder isKindOfClass:[UITabBarController class]]) {
- tempView = [tempView.subviews firstObject];
- if (!tempView) {
- return nil;
- }
- nextResponder = [tempView nextResponder];
- }
- return (UIViewController *)nextResponder;
- }
KVO 监听某个对象的属性
- // 添加监听者
- [self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];
- // 当监听的属性值变化的时候会来到这个方法
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- if ([keyPath isEqualToString:@"property"]) {
- [self textViewTextChange];
- } else {
- }
- }
Reachability 判断网络状态
- NetworkStatus status = [[Reachability reachabilityForInternetConnection] currentReachabilityStatus];
- if (status == NotReachable) {
- NSLog(@"当前设备无网络");
- }
- if (status == ReachableViaWiFi) {
- NSLog(@"当前 wifi 网络");
- }
- if (status == ReachableViaWWAN) {
- NSLog(@"当前蜂窝移动网络");
- }
AFNetworking 监听网络状态
- // 监听网络状况
- AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
- [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
- switch (status) {
- case AFNetworkReachabilityStatusUnknown:
- break;
- case AFNetworkReachabilityStatusNotReachable: {
- NSLog(@"当前设备无网络");
- }
- break;
- case AFNetworkReachabilityStatusReachableViaWiFi:
- NSLog(@"当前 wifi 网络");
- break;
- case AFNetworkReachabilityStatusReachableViaWWAN:
- NSLog(@"当前蜂窝移动网络");
- break;
- default:
- break;
- }
- }];
- [mgr startMonitoring];
父视图透明不影响子视图的做法
self.view.backgroundColor = [[UIColor whiteColor]colorWithAlphaComponent:0.7f];
取图片某一点的颜色
- if (point.x < 0 || point.y < 0) return nil;
- CGImageRef imageRef = self.CGImage;
- NSUInteger width = CGImageGetWidth(imageRef);
- NSUInteger height = CGImageGetHeight(imageRef);
- if (point.x>= width || point.y>= height) return nil;
- unsigned char *rawData = malloc(height * width * 4);
- if (!rawData) return nil;
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- NSUInteger bytesPerPixel = 4;
- NSUInteger bytesPerRow = bytesPerPixel * width;
- NSUInteger bitsPerComponent = 8;
- CGContextRef context = CGBitmapContextCreate(rawData,
- width,
- height,
- bitsPerComponent,
- bytesPerRow,
- colorSpace,
- kCGImageAlphaPremultipliedLast
- | kCGBitmapByteOrder32Big);
- if (!context) {
- free(rawData);
- return nil;
- }
- CGColorSpaceRelease(colorSpace);
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
- CGContextRelease(context);
- int byteIndex = (bytesPerRow * point.y) + point.x * bytesPerPixel;
- CGFloat red = (rawData[byteIndex] * 1.0) / 255.0;
- CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0;
- CGFloat blue = (rawData[byteIndex + 2] * 1.0) / 255.0;
- CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;
- UIColor *result = nil;
- result = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
- free(rawData);
- return result;
判断该图片是否有透明度通道
- - (BOOL)hasAlphaChannel
- {
- CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
- return (alpha == kCGImageAlphaFirst ||
- alpha == kCGImageAlphaLast ||
- alpha == kCGImageAlphaPremultipliedFirst ||
- alpha == kCGImageAlphaPremultipliedLast);
- }
两张图片合成
- + (UIImage*)mergeImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
- CGImageRef firstImageRef = firstImage.CGImage;
- CGFloat firstWidth = CGImageGetWidth(firstImageRef);
- CGFloat firstHeight = CGImageGetHeight(firstImageRef);
- CGImageRef secondImageRef = secondImage.CGImage;
- CGFloat secondWidth = CGImageGetWidth(secondImageRef);
- CGFloat secondHeight = CGImageGetHeight(secondImageRef);
- CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
- UIGraphicsBeginImageContext(mergedSize);
- [firstImage drawInRect:CGRectMake(0, 0, firstWidth, firstHeight)];
- [secondImage drawInRect:CGRectMake(0, 0, secondWidth, secondHeight)];
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return image;
- }
制作水印
- // 画水印
- - (void) setImage:(UIImage *)image withWaterMark:(UIImage *)mark inRect:(CGRect)rect
- {
- if ([[[UIDevice currentDevice] systemVersion] floatValue]>= 4.0)
- {
- UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
- }
- // 原图
- [image drawInRect:self.bounds];
- // 水印图
- [mark drawInRect:rect];
- UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- self.image = newPic;
- }
让 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];
- }
移除字符串中的空格和换行
- + (NSString *)removeSpaceAndNewline:(NSString *)str {
- NSString *temp = [str stringByReplacingOccurrencesOfString:@"" withString:@""];
- temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
- temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
- return temp;
- }
判断字符串中是否有空格
- + (BOOL)isBlank:(NSString *)str {
- NSRange _range = [str rangeOfString:@" "];
- if (_range.location != NSNotFound) {
- // 有空格
- return YES;
- } else {
- // 没有空格
- return NO;
- }
- }
获取一个视频的第一帧图片
- 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;
获取视频的时长
- + (NSInteger)getVideoTimeByUrlString:(NSString *)urlString {
- NSURL *videoUrl = [NSURL URLWithString:urlString];
- AVURLAsset *avUrl = [AVURLAsset assetWithURL:videoUrl];
- CMTime time = [avUrl duration];
- int seconds = ceil(time.value/time.timescale);
- return seconds;
- }
当 tableView 占不满一屏时, 去除下边多余的单元格
- self.tableView.tableHeaderView = [UIView new];
- self.tableView.tableFooterView = [UIView new];
isKindOfClass 和 isMemberOfClass 的区别
isKindOfClass 可以判断某个对象是否属于某个类, 或者这个类的子类.
isMemberOfClass 更加精准, 它只能判断这个对象类型是否为这个类 (不能判断子类)
禁用系统滑动返回功能
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
- if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
- {self.navigationController.interactivePopGestureRecognizer.delegate = self;
- }
- }
- - (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
- if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
- {self.navigationController.interactivePopGestureRecognizer.delegate = nil;
- }
- }
- - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
- {
- return NO;
- }
UILabel 设置内边距
子类化 UILabel, 重写 drawTextInRect 方法
- - (void)drawTextInRect:(CGRect)rect {
- // 边距, 上左下右
- UIEdgeInsets insets = {0, 5, 0, 5};
- [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
- }
UILabel 设置文字描边
子类化 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];
- }
UIView 背景颜色渐变
- + (CAGradientLayer *)setGradualChangingColor:(UIView *)view fromColor:(NSString *)fromHexColorStr toColor:(NSString *)toHexColorStr{
- // CAGradientLayer 类对其绘制渐变背景颜色, 填充层的形状 (包括圆角)
- CAGradientLayer *gradientLayer = [CAGradientLayer layer];
- gradientLayer.frame = view.bounds;
- // 创建渐变色数组, 需要转换为 CGColor 颜色
- gradientLayer.colors = @[(__bridge id)[UIColor colorWithHexString:fromHexColorStr].CGColor,(__bridge id)[UIColor colorWithHexString:toHexColorStr].CGColor];
- // 设置渐变颜色方向, 左下点为 (0,0), 右上点为 (1,1)
- gradientLayer.startPoint = CGPointMake(0, 0.5);
- gradientLayer.endPoint = CGPointMake(1, 0.5);
- // 设置颜色变化点, 取值范围 0.0~1.0
- gradientLayer.locations = @[@0,@1];
- return gradientLayer;
- }
UIView 某个角添加圆角
- // 左上角和右下角添加圆角
- UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(20, 20)];
- CAShapeLayer *maskLayer = [CAShapeLayer layer];
- maskLayer.frame = view.bounds;
- maskLayer.path = maskPath.CGPath;
- view.layer.mask = maskLayer;
UIImage 和 base64 互转
- // view 分类方法
- - (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];
- }
UIWebView 设置背景透明
- [webView setBackgroundColor:[UIColor clearColor]];
- [webView setOpaque:NO];
设置 tableView 分割线颜色以及顶到头
- // 分割线颜色
- [self.tableView setSeparatorColor:[UIColor myColor]];
- // 顶到头
- - (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];
- }
为一个 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];
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];
- }
来源: https://juejin.im/post/5bff9330f265da614d08e56e