打印方法名
NSLog(@"%s",__FUNCTION__);
NSLog(@"%@",NSStringFromSelector(_cmd));
类、方法判断
// 用于判断是否包含某个类方法
respondsToSelector:(SEL)
conformsToProtocol:(Protocol *)
// 判定某个类
isKindOfClass:(__unsafe_unretained Class)
isMemberOfClass:(__unsafe_unretained Class)
// 获取某个类的类名字符串
NSStringFromClass([UITextView class]);
// 通过字符串获取某个类
NSClassFromString(@"UITextView");
emoji表情转换
// 表情转UTF8
[contentstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// UTF8转表情
[content stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
数组和字典与NSData互转
NSArray * arr1 = [[NSArray alloc]initWithObjects:@"0",@"5",nil];
// NSArray->NSData(转字典也使用该方法)
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:arr1];
// NSData->NSArray(转字典也使用该方法)
NSArray * arr2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
字典、JSON互转
// json格式字符串转字典:
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString
{
if (jsonString == nil) {
return nil;
}
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
if(err) {
NSLog(@"json解析失败:%@",err);
return nil;
}
return dic;
}
// 字典转json格式字符串:
+ (NSString*)dictionaryToJson:(NSDictionary *)dic
{
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
自定义结构体(类似于CGSizeMake)
/**
* 分页
*/
struct LBPage{
NSInteger page;
NSInteger number;
};
typedef struct LBPage LBPage;
/**
* 创建分页结构体
*/
CG_INLINE LBPage
LBPageMake(NSInteger page, NSInteger number)
{
LBPage p;
p.page = page;
p.number = number;
return p;
}
实现多选参数(如UIAlertView初始化)
// 定义方法:
- (void)buttonTitles:(nullable NSString *)titles,...;
// 实现方法
- (void)buttonTitles:(nullableNSString *)titles,...{
NSString *other = nil;
va_list args; //用于指向第一个参数
NSMutableArray *fruits = [NSMutableArray array];
if(titles){
[fruits addObject:titles];
// 对args进行初始化,让它指向可变参数表里面的第一个参数
va_start(args, titles);
// 获取指定类型的值
while((other = va_arg(args, NSString*))){
[fruits addObject:other];
}
va_end(args);//将args关闭
}
NSLog(@"%@", fruits);
}
// 方法调用
[self buttonTitles:@“1”,@“2”,nil];
判断当前设备是模拟器还是真机
#if TARGET_IPHONE_SIMULATOR // 模拟器
#define SIMULATOR_TEST 0
#else
#define SIMULATOR_TEST 1
#endif
调试打印
#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"<%s : %d> %s " fmt), [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);
#define NSLog(FORMAT, ...) fprintf(stderr,"%s:%d\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define DLog(...) /* */
#define NSLog(FORMAT, ...) nil
#endif
枚举定义
typedef NS_ENUM(NSInteger,YMDatePickerMode){
YMDatePickerModeTime,
YMDatePickerModeDate,
YMDatePickerDateAndTime,
YMDatePickerModeCountDownTimer
};
typedef enum {
YMDateUnitYear,
YMDateUnitMonth,
YMDateUnitDay
}YMDateUnit;
统音量控制(通过UISlider直接控制系统音量)
// 导入头文件
#import <MediaPlayer/MediaPlayer.h>
// 控制系统音量只需要对slider进行控制即可控制
MPVolumeView *volumeView = [[MPVolumeView alloc] init];
[volumeView sizeToFit];
NSLog(@"%@",volumeView.subviews);
// 将系统的音量调整视图赋给自定义的UISlider,实现拖动自定义UISlider直接改变系统音量
UISlider * slider = [[UISlider alloc]init];
slider.backgroundColor = [UIColor blueColor];
for (UIControl *view in volumeView.subviews) {
if ([view.superclass isSubclassOfClass:[UISlider class]]) {
slider = (UISlider *)view;
}
}
slider.autoresizesSubviews = NO;
slider.autoresizingMask = UIViewAutoresizingNone;
slider.hidden = YES;
NSLog(@"_backVolumeView.value = %lf",_backVolumeView.value);
获取系统音量
#import <AVFoundation/AVFoundation.h> 监听系统音量
// 创建监听
NSError *error;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
// 开始接收远程控制事件
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
// 结束接收远程控制事件
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
// 获取音量
- (void)volumeChanged:(NSNotification *)notification
{
NSLog(@"volume = %@",notification.userInfo);
}
截取当前屏幕
// currentView 当前的view 创建一个基于位图的图形上下文并指定大小为
UIGraphicsBeginImageContext(self.view.bounds.size);
// renderInContext呈现接受者及其子范围到指定的上下文
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
// 返回一个基于当前图形上下文的图片
_currentScreen = UIGraphicsGetImageFromCurrentImageContext();
// 移除栈顶的基于当前位图的图形上下文
UIGraphicsEndImageContext();
// 然后将该图片保存到图片图
UIImageWriteToSavedPhotosAlbum(_currentScreen, nil, nil, nil);
截取视频帧图片
- (void)thumbnailImageForVideo:(NSString *)videoPath atTime:(NSTimeInterval)time success:(void(^)(UIImage *image))success
{
dispatch_queue_t globQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globQueue, ^{
// 通过视频路径获取AVURLAsset
NSURL * vedioURL = [NSURL URLWithString:videoPath];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vedioURL options:nil];
NSParameterAssert(asset);
AVAssetImageGenerator *assetImageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
assetImageGenerator.appliesPreferredTrackTransform = YES;
assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
CGImageRef thumbnailImageRef = NULL;
CFTimeInterval thumbnailImageTime = time;
NSError *thumbnailImageGenerationError = nil;
thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60) actualTime:NULL error:&thumbnailImageGenerationError];
if (!thumbnailImageRef) {
NSLog(@"thumbnailImageGenerationError %@", thumbnailImageGenerationError);
}
UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc] initWithCGImage:thumbnailImageRef] : nil;
dispatch_async(dispatch_get_main_queue(), ^{
success(thumbnailImage);
});
});
}
获取当前设备是iPad还是iPhone
// 判断是否为pad
UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
// 获取当前iPhone型号
- (NSString*)deviceVersion
{
// 需要#import "sys/utsname.h"
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
//CLog(@"%@",deviceString);
if ([deviceString isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
if ([deviceString isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
if ([deviceString isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
if ([deviceString isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
if ([deviceString isEqualToString:@"iPhone3,2"]) return @"Verizon iPhone 4";
if ([deviceString isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([deviceString isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
if ([deviceString isEqualToString:@"iPhone6,2"]) return @"iPhone 5S";
if ([deviceString isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
if ([deviceString isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
if ([deviceString isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
if ([deviceString isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
if ([deviceString isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
if ([deviceString isEqualToString:@"iPad1,1"]) return @"iPad";
if ([deviceString isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)";
if ([deviceString isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)";
if ([deviceString isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)";
if ([deviceString isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)";
if ([deviceString isEqualToString:@"i386"]) return @"Simulator";
if ([deviceString isEqualToString:@"x86_64"]) return @"Simulator";
//CLog(@"NOTE: Unknown device type: %@", deviceString);
return deviceString;
}
block
// 定义
typedef void (^MyBlock)();
@property (nonatomic, copy) MyBlock buttonAction;
// 定义
@property (nonatomic, copy)void(^dimissCompleteBlock)(void);
// 定义
- (void)checkBlockResult:(void(^)(NSInteger))result;
// block可抽出来:
// 定义
- (void)didFinish:(void (^)(void))didFinish;
// 调用
[self didFinish:didFinishPlay]]
// 实现
void (^didFinishPlay)(void) = ^(){
};
判断字符串中是否有表情
- (BOOL)stringContainsEmoji:(NSString *)string
{
__block BOOL returnValue = NO;
void (^didFinishPlay)() = ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
const unichar hs = [substring characterAtIndex:0];
// surrogate pair
if (0xd800 <= hs && hs <= 0xdbff) {
if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
returnValue = YES;
}
}
} else if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
if (ls == 0x20e3) {
returnValue = YES;
}
} else {
// non surrogate
if (0x2100 <= hs && hs <= 0x27ff) {
returnValue = YES;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
returnValue = YES;
} else if (0x2934 <= hs && hs <= 0x2935) {
returnValue = YES;
} else if (0x3297 <= hs && hs <= 0x3299) {
returnValue = YES;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
returnValue = YES;
}
}
};
[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:didFinishPlay];
return returnValue;
}
CALayout图片平铺(可用于AVPlayer的预览图设置)
self.view.layer.contents = (__bridge id)[UIImage imageNamed:@"demo"].CGImage;
屏幕旋转
// 允许屏幕自动旋转
// 该方法在只有UIVIewController的状况下 会被调用
// 是否允许自转
- (BOOL)shouldAutorotate
{
return YES;
}
// 当将UIViewController加载到UINavigationController上时 - (BOOL)shouldAutorotate不被调用(解决方案查看下一个方法)
// 在工程需要中需要调用的控制器中加入下列代码(LoadingViewController)
@implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
@end
// 屏幕旋转
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight );
}
// 屏幕旋转
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
// 屏幕支持的方向
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
// 手动旋转屏幕(电池栏也会跟着旋转)
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = (int)UIInterfaceOrientationLandscapeRight;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
// 默认旋转方向
1.打开项目Supporting Files文件夹中的info.plist
2.找到Supported interface orientations
3.改变item的顺序,如果right在前面 left在后面,那么屏幕默认以left方向为准
解决控制器dismiss时,被覆盖的界面自动旋转
// 1、在 - (void)viewDidLoad 或者 - (void)viewWillAppear:(BOOL)animated中加入以下代码
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
//orientation
[[UIApplication sharedApplication]
setStatusBarOrientation:UIInterfaceOrientationPortrait
animated:NO];
[[UIDevice currentDevice]
setValue:[NSNumber
numberWithInteger:UIInterfaceOrientationPortrait]
forKey:@"orientation"];
}
// 2、重写以下方法
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
// 返回所需要的方向,可以是多个方向
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
// 返回所需要的方向,可以是多个方向
returnUIInterfaceOrientationPortrait;
}
获取启动页和设置启动页延时(LaunchView)
UIView * launchView = [[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:nil options:nil][0];
launchView.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
[self.window addSubview:launchView];
[NSThread sleepForTimeInterval:0.4];
点击推送通知进入APP 显示通知内容
// 当点击推送通知时 下面方法中的launchOptions会有数据
// 因此可以由此去判断当前是否是点击推送进入的APP
// 可以设置全局变量来记录
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
// 此时必然会调用下面的方法
// 可以获取userInfo中的内容
// 字段分别是 alert badge sound
// 通过userInfo[@"aps"][@"alert”]获取
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
iOS 7.0 用该方法
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
// 判断是否通过推送界面进入
NSDictionary* remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification)
{
_isLaunchedByNotification = 1;
}
获取版本号Version
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
字体大小自动调整
// 按钮、标签都可以进行自动调整
button.titleLabel.adjustsFontSizeToFitWidth = YES;
// 调增范围(字体大小最多缩小到某个比率)
button.titleLabel.minimumScaleFactor = 0.5;
获取runtime中的私有属性
获取下图中红框中的属性名
私有属性
// 1.申明一个类目并写好实现逻辑
@interface NSObject (RuntimeUntility)
- (id)getPrivateProperty:(NSString *)propertyName;
@end
@implementation NSObject (RuntimeUntility)
- (id)getPrivateProperty:(NSString *)propertyName
{
Ivar iVar = class_getInstanceVariable([self class], [propertyName UTF8String]);
if (iVar == nil) {
iVar = class_getInstanceVariable([self class], [[NSString stringWithFormat:@"_%@",propertyName] UTF8String]);
}
id propertyVal = object_getIvar(self, iVar);
return propertyVal;
}
@end
// 2.进行调用,传入参数填写要获取的属性的名称,如果runtime中有有下滑线(如_bqmmExtra)要对其删除
id bqmmExtra = [messageContent getPrivateProperty:@"bqmmExtra"];
pragma mark - 安装包获
1.打开活动监视器
2.找到storedownload
3.点击图标
4.复制一下路径,到指定路径下获取包,在安装之前把他拖出来
处理本地缓存
1.搜索路径:/Users/huangyuzhou(用户名)/Library/Developer/Xcode
(注:Library资源库是隐藏的文件夹)
2.删除里面文件即可(里面有DerivedData和Snapshots两个文件夹,)
自动内存管理 手动内存管理混编
可以在build phases 下的compile sources 中找到不想自动管理的.m文件 ,给它加compiler flags 为 -fno-objc-arc
Xcode真机调试包
Xcode版本不支持高版本手机时,可拖入高版本包,从而不需要更新Xcode,而进行真机测试。路径:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
正则表达式
// 含有字母和数字的6~16位字符串
NSString * passwordRegex = @"^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$";
模糊效果
//加模糊效果,image是图片,blur是模糊度
- (UIImage *)blurryImage:(UIImage *)image withBlurLevel:(CGFloat)blur {
//模糊度,
if ((blur < 0.1f) || (blur > 2.0f)) {
blur = 0.5f;
}
//boxSize必须大于0
int boxSize = (int)(blur * 100);
boxSize -= (boxSize % 2) + 1;
NSLog(@"boxSize:%i",boxSize);
//图像处理
CGImageRef img = image.CGImage;
//需要引入
/*
This document describes the Accelerate Framework, which contains C APIs for vector and matrix math, digital signal processing, large number handling, and image processing.
本文档介绍了Accelerate Framework,其中包含C语言应用程序接口(API)的向量和矩阵数学,数字信号处理,大量处理和图像处理。
*/
//图像缓存,输入缓存,输出缓存
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
//像素缓存
void *pixelBuffer;
//数据源提供者,Defines an opaque type that supplies Quartz with data.
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
// provider’s data.
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
//宽,高,字节/行,data
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);
inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
//像数缓存,字节行*图片高
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(img);
outBuffer.height = CGImageGetHeight(img);
outBuffer.rowBytes = CGImageGetBytesPerRow(img);
// 第三个中间的缓存区,抗锯齿的效果
void *pixelBuffer2 = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
vImage_Buffer outBuffer2;
outBuffer2.data = pixelBuffer2;
outBuffer2.width = CGImageGetWidth(img);
outBuffer2.height = CGImageGetHeight(img);
outBuffer2.rowBytes = CGImageGetBytesPerRow(img);
//Convolves a region of interest within an ARGB8888 source image by an implicit M x N kernel that has the effect of a box filter.
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
error = vImageBoxConvolve_ARGB8888(&outBuffer2, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
// NSLog(@"字节组成部分:%zu",CGImageGetBitsPerComponent(img));
//颜色空间DeviceRGB
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//用图片创建上下文,CGImageGetBitsPerComponent(img),7,8
CGContextRef ctx = CGBitmapContextCreate(
outBuffer.data,
outBuffer.width,
outBuffer.height,
8,
outBuffer.rowBytes,
colorSpace,
CGImageGetBitmapInfo(image.CGImage));
//根据上下文,处理过的图片,重新组件
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
//clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
free(pixelBuffer2);
CFRelease(inBitmapData);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageRef);
return returnImage;
}
Gif图的两种播放方式
#import "ViewController.h"
#import <WebKit/WebKit.h>
#import <ImageIO/ImageIO.h>
/*
经过测试,从加载速度上来说,通过UIImageView类别加载的方式更加快速,UIWebView的方式加载时间会稍长,但是从性能上来比较,WebView的方式性能更优,播放的gif动态图更加流畅。
在开发中,可以根据需求,适当选择,例如虽然WebView加载的方式性能更好,但是在许多情况下,原生的UIImageView能够更加自由的让开发者进行扩展。
*/
/*
UIImage+GitImageView
*/
@interface UIImageView (GitImageView)
@end
@implementation UIImageView (GitImageView)
// 为UIImageView添加一个设置gif图内容的方法:
-(void)yh_setImage:(NSURL *)imageUrl{
__weak id __self = self;
[self getGifImageWithUrk:imageUrl returnData:^(NSArray<UIImage *> *imageArray, NSArray<NSNumber *> *timeArray, CGFloat totalTime, NSArray<NSNumber *> *widths, NSArray<NSNumber *> *heights) {
// 展示第一张图片
if (0) {
UIImage * image = imageArray[0];
self.image = image;
}
// 展示帧动画
else{
//添加帧动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
NSMutableArray * times = [[NSMutableArray alloc]init];
float currentTime = 0;
NSMutableArray * imageRefs = [NSMutableArray array];
for (UIImage * newImage in imageArray) {
CGImageRef imageRef = newImage.CGImage;
[imageRefs addObject:(__bridge UIImage *)imageRef];
}
//设置每一帧的时间占比
for (int i=0; i<imageRefs.count; i++) {
[times addObject:[NSNumber numberWithFloat:currentTime/totalTime]];
currentTime+=[timeArray[i] floatValue];
}
[animation setKeyTimes:times];
[animation setValues:imageRefs];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
//设置循环
animation.repeatCount= MAXFLOAT;
//设置播放总时长
animation.duration = totalTime;
//Layer层添加
[[(UIImageView *)__self layer]addAnimation:animation forKey:@"gifAnimation"];
}
}];
}
//解析gif文件数据的方法 block中会将解析的数据传递出来
-(void)getGifImageWithUrk:(NSURL *)url
returnData:(void(^)(NSArray<UIImage *> * imageArray,
NSArray<NSNumber *>*timeArray,
CGFloat totalTime,
NSArray<NSNumber *>* widths,
NSArray<NSNumber *>* heights))dataBlock{
//通过文件的url来将gif文件读取为图片数据引用
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
//获取gif文件中图片的个数
size_t count = CGImageSourceGetCount(source);
//定义一个变量记录gif播放一轮的时间
float allTime=0;
//存放所有图片
NSMutableArray * imageArray = [[NSMutableArray alloc]init];
//存放每一帧播放的时间
NSMutableArray * timeArray = [[NSMutableArray alloc]init];
//存放每张图片的宽度 (一般在一个gif文件中,所有图片尺寸都会一样)
NSMutableArray * widthArray = [[NSMutableArray alloc]init];
//存放每张图片的高度
NSMutableArray * heightArray = [[NSMutableArray alloc]init];
//遍历
for (size_t i=0; i<count; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
UIImage * image = [UIImage imageWithCGImage:imageRef];
[imageArray addObject:image];
CGImageRelease(imageRef);
//获取图片信息
NSDictionary * info = (__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(source, i, NULL);
CGFloat width = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelWidth] floatValue];
CGFloat height = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelHeight] floatValue];
[widthArray addObject:[NSNumber numberWithFloat:width]];
[heightArray addObject:[NSNumber numberWithFloat:height]];
NSDictionary * timeDic = [info objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary];
CGFloat time = [[timeDic objectForKey:(__bridge NSString *)kCGImagePropertyGIFDelayTime]floatValue];
allTime+=time;
[timeArray addObject:[NSNumber numberWithFloat:time]];
}
CFRelease(source);
dataBlock(imageArray,timeArray,allTime,widthArray,heightArray);
}
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 加载Gif图方法一:使用webView加载,需要导入#import <WebKit/WebKit.h>
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(100, 100, 150, 150)];
[self.view addSubview:webView];
NSURL * URL = [NSURL URLWithString:@"http://qq.yh31.com/tp/zr/zr168.gif"];
NSURLRequest * request = [NSURLRequest requestWithURL:URL];
[webView loadRequest:request];
// 取消回弹效果
webView.scrollView.bounces=NO;
webView.backgroundColor = [UIColor clearColor];
// 设置缩放模式
webView.userInteractionEnabled = NO;
// 加载Gif图方法二:使用ImageIO库
UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100 ,300 , 150, 150)];
NSURL * url = URL;
[imageView yh_setImage:url];
[self.view addSubview:imageView];
}
@end
自定义代码模板
- 进入到
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/Source
目录下 - 任意拷贝其中一个模板,并改名为MyClass.xctemplate,后缀.xctemplate新建文件试试,是不是有MyClass这个文件模板了呢
快捷打包方式
-
切换到图中的情况,进行commond + B 编译一次。
-
找到图中.app后缀的文件,到文件所在路径,将文件拷贝一份到桌面
-
在桌面创建一个名为"Payload"的文件夹,将刚刚的.app文件拖入,然后压缩,压缩完成后将安装包后缀改成.ipa
网友评论