共计 25597 个字符,预计需要花费 64 分钟才能阅读完成。
本文主要记录日常工作中积累的一些 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];
动画切换 window 的根控制器
[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))
获取 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;
}
修改 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 *window = [[UIApplication sharedApplication].windows firstObject];
if (!window) {
return nil;
}
UIView *tempView;
for (UIView *subview in window.subviews) {
if ([[subview.classForCoder description] isEqualToString:@”UILayoutContainerView”]) {
tempView = subview;
break;
}
}
if (!tempView) {
tempView = [window.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];
}