接下來我們看Base文件夾下的UIKIt文件夾的內容卫袒。
1.UIColor+YYAdd
這里看了這個類桃熄,里面有許多顏色之間的轉換卦停,因此借此機會弦悉,順便看看顏色之間的轉換原理
RGB2HSL
HSL 色調飽和亮度模式 摘自文章
H色調 0~360 圓環(huán)形式 以角度表示
S 飽和度 0~1 之間的小數(shù)
L 亮度 0~1 之間的小數(shù)
什么是純色
先來看一下windows的拾色器
最上頭黑色框里面那些顏色 最最最頂端的部分耿戚。
是不是感覺他們最鮮艷 最惹眼湿故,嗯 因為他們RGB之間的差異化最大
RGB產生顏色的原理就是RGB三個能量值產生差異化 組合。
所以我們才能看到這些花花綠綠的顏色膜蛔。
純色一個特點那就是最大值跟最小值的差是255 坛猪,差異達到最大。
也就是說RGB一定有一個顏色是0 一個是255飞几,否則不能稱之為純色
純亮度表示就是只能量值沒有差異 也指灰度圖
純色的計算
通過觀察windows畫圖板拾色器 就是上面中間那個破圖砚哆。我們知道 如果飽和度固定為1 亮度固定為0.5 独撇,那么色調即純色 純色即色調屑墨。純色的定義參見上面。
從RGB值的變化規(guī)律可以看出色調的變化是連續(xù)平緩 首尾相接的 可以看成是一個360度的圓 紅色是0度纷铣。他的變化規(guī)律是:
三個規(guī)律
1至始至終都有一個值是0 一個值是255卵史。
2整個過程中同一時間總是只有一個值在變
3三個數(shù)的全排列 那么總共有6種組合
但是首先有一點要明確: 上面餅圖的一塊 就是60度 值是255
我們把色調分成1~360的表現(xiàn)形式,但是RGB是以(255,255,255)的表現(xiàn)形式 那么他們之間怎么對應呢搜立?那就是60度=255
每前進一度scale+=(255*6)*(1/360)
RGB可以表達255*255*255=16581375種顏色 但是他可以表達的純色只有255*6=1530種
所以HSL 標示的顏色能少點(所以RGB 轉換成HSL 肯定是要少顏色值的)
通過上面我們知道了H的色值標示范圍
接下來我們看看HLS的定義
HSL在數(shù)學上定義為在 RGB 空間中的顏色的R,G和B的坐標的變換以躯。
從 RGB 到 HSL ?的轉換
設 (r,g,b) 分別是一個顏色的紅、綠和藍坐標啄踊,它們的值是在 0 到 1 之間的實數(shù)忧设。設max等價于r,g和b中的最大者。設min等于這些值中的最小者颠通。要找到在 HSL 空間中的 (h,s,l) 值址晕,這里的h∈ [0, 360)是角度的色相角,而s,l∈ [0,1] 是飽和度和亮度顿锰,計算為:
h的值通常規(guī)范化到位于 0 到 360°之間。而h= 0 用于max=min的(就是灰色)時候而不是留下h未定義刘陶。
從 RGB 到 HSV 的轉換
色相和HSL 一樣sv不一樣而已
從 HSL 到 RGB 的轉換
給定 HSL 空間中的 (h,s,l) 值定義的一個顏色胳赌,帶有h在指示色相角度的值域 [0, 360)中,分別表示飽和度和亮度的s和l在值域 [0, 1] 中匙隔,相應在 RGB 空間中的 (r,g,b) 三原色疑苫,帶有分別對應于紅色、綠色和藍色的r,g和b也在值域 [0, 1] 中纷责,它們可計算為:
首先缀匕,如果s= 0,則結果的顏色是非彩色的碰逸、或灰色的乡小。在這個特殊情況,r,g和b都等于l饵史。注意h的值在這種情況下是未定義的满钟。
當s≠ 0 的時候,可以使用下列過程
這里定義了好多顏色轉換是c語言寫的胳喷。這里不想做過多介紹
void YY_RGB2HSL(CGFloat r, CGFloat g, CGFloat b,CGFloat *h, CGFloat *s, CGFloat *l)
void YY_HSL2RGB(CGFloat h, CGFloat s, CGFloat l,CGFloat *r, CGFloat *g, CGFloat *b)
void YY_RGB2HSB(CGFloat r, CGFloat g, CGFloat b,CGFloat *h, CGFloat *s, CGFloat *v)
void YY_HSB2RGB(CGFloat h, CGFloat s, CGFloat v,CGFloat *r, CGFloat *g, CGFloat *b)
void YY_RGB2CMYK(CGFloat r, CGFloat g, CGFloat b,CGFloat *c, CGFloat *m, CGFloat *y, CGFloat *k)
void YY_CMYK2RGB(CGFloat c, CGFloat m, CGFloat y, CGFloat k,CGFloat *r, CGFloat *g, CGFloat *b)
void YY_HSB2HSL(CGFloat h, CGFloat s, CGFloat b,CGFloat *hh, CGFloat *ss, CGFloat *ll)
void YY_HSL2HSB(CGFloat h, CGFloat s, CGFloat l,CGFloat *hh, CGFloat *ss, CGFloat *bb)
顏色之間的相互轉換
+ (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)lightness alpha:(CGFloat)alpha
就是用hsL 顏色空間湃番,由于系統(tǒng)默認的是rgb 將hsl 轉換成了RGB
+ (UIColor *)colorWithCyan:(CGFloat)cyan magenta:(CGFloat)magenta yellow:(CGFloat)yellow black:(CGFloat)black alpha:(CGFloat)alpha
cmyk 轉換成rgb
+ (UIColor *)colorWithRGB:(uint32_t)rgbValue {
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0f
green:((rgbValue & 0xFF00) >> 8) / 255.0f
blue:(rgbValue & 0xFF) / 255.0f
alpha:1];
這個傳入的是一個顏色值,位操作
+ (UIColor *)colorWithRGBA:(uint32_t)rgbaValue {
return [UIColor colorWithRed:((rgbaValue & 0xFF000000) >> 24) / 255.0f
green:((rgbaValue & 0xFF0000) >> 16) / 255.0f
blue:((rgbaValue & 0xFF00) >> 8) / 255.0f
alpha:(rgbaValue & 0xFF) / 255.0f];
}
帶有alpha 通道的RGBA
+ (UIColor *)colorWithRGB:(uint32_t)rgbValue alpha:(CGFloat)alpha {
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0f
green:((rgbValue & 0xFF00) >> 8) / 255.0f
blue:(rgbValue & 0xFF) / 255.0f
alpha:alpha];
}
RGBA 傳入?yún)?shù)不一致而已
- (uint32_t)rgbValue {
CGFloat r = 0, g = 0, b = 0, a = 0;
[self getRed:&r green:&g blue:&b alpha:&a];
int8_t red = r * 255;
uint8_t green = g * 255;
uint8_t blue = b * 255;
return (red << 16) + (green << 8) + blue;
}
獲取rgb值吭露,不帶a通道
- (uint32_t)rgbaValue {
CGFloat r = 0, g = 0, b = 0, a = 0;
[self getRed:&r green:&g blue:&b alpha:&a];
int8_t red = r * 255;
uint8_t green = g * 255;
uint8_t blue = b * 255;
uint8_t alpha = a * 255;
return (red << 24) + (green << 16) + (blue << 8) + alpha;
}
獲取rgba?
static inline NSUInteger hexStrToInt(NSString *str) {
uint32_t result = 0;
sscanf([str UTF8String], "%X", &result);
return result;
}
內斂函數(shù)吠撮, ?這個將str 轉換成 int值
static BOOL hexStrToRGBA(NSString *str,
CGFloat *r, CGFloat *g, CGFloat *b, CGFloat *a)
str = [[str stringByTrim] uppercaseString];
if ([str hasPrefix:@"#"]) {
str = [str substringFromIndex:1];
} else if ([str hasPrefix:@"0X"]) {
str = [str substringFromIndex:2];
}
NSUInteger length = [str length];
//? ? ? ? RGB? ? ? ? ? ? RGBA? ? ? ? ? RRGGBB? ? ? ? RRGGBBAA
if (length != 3 && length != 4 && length != 6 && length != 8) {
return NO;
}
//RGB,RGBA,RRGGBB,RRGGBBAA
if (length < 5) {
*r = hexStrToInt([str substringWithRange:NSMakeRange(0, 1)]) / 255.0f;
*g = hexStrToInt([str substringWithRange:NSMakeRange(1, 1)]) / 255.0f;
*b = hexStrToInt([str substringWithRange:NSMakeRange(2, 1)]) / 255.0f;
if (length == 4)? *a = hexStrToInt([str substringWithRange:NSMakeRange(3, 1)]) / 255.0f;
else *a = 1;
} else {
*r = hexStrToInt([str substringWithRange:NSMakeRange(0, 2)]) / 255.0f;
*g = hexStrToInt([str substringWithRange:NSMakeRange(2, 2)]) / 255.0f;
*b = hexStrToInt([str substringWithRange:NSMakeRange(4, 2)]) / 255.0f;
if (length == 8) *a = hexStrToInt([str substringWithRange:NSMakeRange(6, 2)]) / 255.0f;
else *a = 1;
}
return YES;
}
適配了各種書寫形式RGB,RGBA,RRGGBB,RRGGBBAA 帶# 或者0X 或者不帶都可以
+ (instancetype)colorWithHexString:(NSString *)hexStr
- (NSString *)hexString
- (NSString *)hexStringWithAlpha
基礎不做介紹
- (NSString *)hexStringWithAlpha:(BOOL)withAlpha {
CGColorRef color = self.CGColor;
size_t count = CGColorGetNumberOfComponents(color);
const CGFloat *components = CGColorGetComponents(color);
static NSString *stringFormat = @"%02x%02x%02x";
NSString *hex = nil;
if (count == 2) {
NSUInteger white = (NSUInteger)(components[0] * 255.0f);
hex = [NSString stringWithFormat:stringFormat, white, white, white];
} else if (count == 4) {
hex = [NSString stringWithFormat:stringFormat,
(NSUInteger)(components[0] * 255.0f),
(NSUInteger)(components[1] * 255.0f),
(NSUInteger)(components[2] * 255.0f)];
}
if (hex && withAlpha) {
hex = [hex stringByAppendingFormat:@"%02lx",
(unsigned long)(self.alpha * 255.0 + 0.5)];
}
return hex;
}
這里分為 count=2 和count = 4 黑白形式count=2(CGColorCreateGenericGray) 普通形式count=4
- (UIColor *)colorByAddColor:(UIColor *)add blendMode:(CGBlendMode)blendMode {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
uint8_t pixel[4] = { 0 };
CGContextRef context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, bitmapInfo);
CGContextSetFillColorWithColor(context, self.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
CGContextSetBlendMode(context, blendMode);
CGContextSetFillColorWithColor(context, add.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return [UIColor colorWithRed:pixel[0] / 255.0f green:pixel[1] / 255.0f blue:pixel[2] / 255.0f alpha:pixel[3] / 255.0f];
}
kCGImageAlphaPremultipliedLast 是顏色編排采用RGBA模式
kCGBitmapByteOrder32Big ?才有32 大字節(jié)序
大端字節(jié)(Big-endian):
----------------->>>>>>>>內存地址增大方向
short變量地址
0x1000????????????????? 0x1001
_____________________________
|?????????????????????????? |
|???????? 0x31???????????? |?????? 0x32
|________________ | ________________
高位字節(jié)在低位字節(jié)的前面,也就是高位在內存地址低的一端.可以這樣記住(大端->高位->在前->正常的邏輯順序)
小端字節(jié)(little-endian):
----------------->>>>>>>>內存地址增大方向
short變量地址
0x1000????????????????? 0x1001
_____________________________
|?????????????????????????? |
|???????? 0x32???????????? |?????? 0x31
|________________ | ________________
低位字節(jié)在高位字節(jié)的前面,也就是低位在內存地址低的一端.可以這樣記住(小端->低位->在前->與正常邏輯順序相反)
? ?就是規(guī)定bitmap 的采用RGBA 32位 在內存中
這里函數(shù)就是顏色之間的融合,根據(jù)CGBlendMode模式
什么是CGBlendMode模式呢
Overview
These blend mode constants represent the Porter-Duff blend modes. The symbols in the equations for these blend modes are:
R is the premultiplied result
S is the source color, and includes alpha
D is the destination color, and includes alpha
Ra, Sa, and Da are the alpha components of R, S, and D
You can find more information on blend modes, including examples of images produced using them, and many mathematical descriptions of the modes, inPDF Reference, Fourth Edition, Version 1.5, Adobe Systems, Inc. If you are a former QuickDraw developer, it may be helpful for you to think of blend modes as an alternative to transfer modes
那我們就看看什么是Porter-Duff讲竿。這里有篇博客做介紹
R 是結果
S是source 帶有alpha
D 是目標顏色 帶有alpha
Ra Sa泥兰,Da 是代表R S D 的透明度
說白了就是兩種顏色融合的模式。
- (UIColor *)colorByChangeHue:(CGFloat)h saturation:(CGFloat)s brightness:(CGFloat)b alpha:(CGFloat)a
增加HSL 的顏色
- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation lightness:(CGFloat *)lightness alpha:(CGFloat *)alpha
- (BOOL)getCyan:(CGFloat *)cyan magenta:(CGFloat *)magenta yellow:(CGFloat *)yellow
black:(CGFloat *)black alpha:(CGFloat *)alpha
- (CGFloat)red
- (CGFloat)green
- (CGFloat)blue
- (CGFloat)alpha
- (CGFloat)hue
- (CGFloat)saturation
- (CGFloat)brightness
- (CGColorSpaceModel)colorSpaceModel
- (NSString *)colorSpaceString
簡單不做介紹
2.UIImage+YYAdd
這個類好長啊题禀。慢慢看吧
+ (UIImage *)imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale
獲取gif 圖片?
這個函數(shù)分段看
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFTypeRef)(data), NULL);
if (!source) return nil;
size_t count = CGImageSourceGetCount(source);
if (count <= 1) {
CFRelease(source);
return [self.class imageWithData:data scale:scale];
}
1將gif NSData 轉換成source 鞋诗,這個source 包含了gif圖的一些基本信息。
2 檢查gif 動圖的圖片數(shù)量迈嘹。要是小于或者等于一張削彬,就直接生成圖片就行了。
NSUInteger frames[count];
double oneFrameTime = 1 / 50.0; // 50 fps
NSTimeInterval totalTime = 0;
NSUInteger totalFrame = 0;
NSUInteger gcdFrame = 0;
for (size_t i = 0; i < count; i++) {
NSTimeInterval delay = _yy_CGImageSourceGetGIFFrameDelayAtIndex(source, i);
totalTime += delay;
NSInteger frame = lrint(delay / oneFrameTime);
if (frame < 1) frame = 1;
frames[i] = frame;
totalFrame += frames[i];
if (i == 0) gcdFrame = frames[i];
else {
NSUInteger frame = frames[i], tmp;
if (frame < gcdFrame) {
tmp = frame; frame = gcdFrame; gcdFrame = tmp;
}
while (true) {
tmp = frame % gcdFrame;
if (tmp == 0) break;
frame = gcdFrame;
gcdFrame = tmp;
}
}
}
1定義變量秀仲,從命名可以看出是干啥用的融痛。
2.這里主要看for循環(huán),
NSTimeInterval delay = _yy_CGImageSourceGetGIFFrameDelayAtIndex(source, i);
static NSTimeInterval _yy_CGImageSourceGetGIFFrameDelayAtIndex(CGImageSourceRef source, size_t index) {
NSTimeInterval delay = 0;
CFDictionaryRef dic = CGImageSourceCopyPropertiesAtIndex(source, index, NULL);
if (dic) {
CFDictionaryRef dicGIF = CFDictionaryGetValue(dic, kCGImagePropertyGIFDictionary);
if (dicGIF) {
NSNumber *num = CFDictionaryGetValue(dicGIF, kCGImagePropertyGIFUnclampedDelayTime);
if (num.doubleValue <= __FLT_EPSILON__) {
num = CFDictionaryGetValue(dicGIF, kCGImagePropertyGIFDelayTime);
}
delay = num.doubleValue;
}
CFRelease(dic);
}
// http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility
if (delay < 0.02) delay = 0.1;
return delay;
}
這個c函數(shù)干啥了呢
1.獲取gif 沒一張圖片的屬性保存在dic中
2.如果有屬性dic 神僵,那么獲取kCGImagePropertyGIFDictionary 字典的值
3.如果獲取到了gif 字典雁刷,獲取delay時間。
4.要是delay 時間小于0.02 那么設置為0.1?
不過所有人的設置大小是0.011s 墩崩。yykit這里設置的是0.02 秒。沒查到相關技術指標侯勉。不做評論
返回for循環(huán)接著看
3.將圖片間隔時間累加到totaltime變量上
rint, rintf, rintl, lrint, lrintf, lrintl, llrint, llrintf, llrintl
定義于頭文件
floatrintf(floatarg);(1)(C99 起)
doublerint(doublearg);(2)(C99 起)
longdoublerintl(longdoublearg);(3)(C99 起)
定義于頭文件
#define rint( arg )(4)(C99 起)
定義于頭文件
longlrintf(floatarg);(5)(C99 起)
longlrint(doublearg);(6)(C99 起)
longlrintl(longdoublearg);(7)(C99 起)
定義于頭文件
#define lrint( arg )(8)(C99 起)
定義于頭文件
longlongllrintf(floatarg);(9)(C99 起)
longlongllrint(doublearg);(10)(C99 起)
longlongllrintl(longdoublearg);(11)(C99 起)
定義于頭文件
#define llrint( arg )(12)(C99 起)
1-3)用當前舍入模式鹦筹,舍入浮點參數(shù)arg為整數(shù)值(以浮點格式)。
5-7, 9-11)用當前舍入模式址貌,舍入浮點參數(shù)arg為整數(shù)值铐拐。
4,8,12)泛型宏:若arg擁有l(wèi)ongdouble類型,练对,則調用rintl遍蟋、lrintl、llrintl螟凭。否則若arg擁有整數(shù)或double類型虚青,則調用rint、lrint螺男、llrint棒厘。否則分別調用rintf、lrintf下隧、llrintf奢人。
lrint 函數(shù)用法
4 保存frame 。累加totalFrame
5.gcdFrame 保存第一次的frame
6.檢查后面的frame 淆院,要是比gcdFrame 小何乎,就gcdFrame 保存最小的frame
7.獲取最小公約數(shù)?
NSMutableArray *array = [NSMutableArray new];
8.生成一個數(shù)組
for (size_t i = 0; i < count; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!imageRef) {
CFRelease(source);
return nil;
}
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
if (width == 0 || height == 0) {
CFRelease(source);
CFRelease(imageRef);
return nil;
}
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
BOOL hasAlpha = NO;
if (alphaInfo == kCGImageAlphaPremultipliedLast ||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
alphaInfo == kCGImageAlphaLast ||
alphaInfo == kCGImageAlphaFirst) {
hasAlpha = YES;
}
// BGRA8888 (premultiplied) or BGRX8888
// same as UIGraphicsBeginImageContext() and -[UIView drawRect:]
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, bitmapInfo);
CGColorSpaceRelease(space);
if (!context) {
CFRelease(source);
CFRelease(imageRef);
return nil;
}
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); // decode
CGImageRef decoded = CGBitmapContextCreateImage(context);
CFRelease(context);
if (!decoded) {
CFRelease(source);
CFRelease(imageRef);
return nil;
}
UIImage *image = [UIImage imageWithCGImage:decoded scale:scale orientation:UIImageOrientationUp];
CGImageRelease(imageRef);
CGImageRelease(decoded);
if (!image) {
CFRelease(source);
return nil;
}
for (size_t j = 0, max = frames[i] / gcdFrame; j < max; j++) {
[array addObject:image];
}
}
9 進入for循環(huán)
10 通過source 獲取image 土辩,要是沒有image 那么就返回了nil
11.獲取沒張image的長度寬度 還有alpha
kCGBitmapAlphaInfoMask 這里出現(xiàn)這個東西支救,干啥的,看了半天沒懂啥意思脯燃。
不經意間看見了這個東西
typedef CF_ENUM(uint32_t, CGImageByteOrderInfo) {
kCGImageByteOrderMask? ? = 0x7000,
kCGImageByteOrder16Little = (1 << 12),
kCGImageByteOrder32Little = (2 << 12),
kCGImageByteOrder16Big? ? = (3 << 12),
kCGImageByteOrder32Big? ? = (4 << 12)
}
這里也出現(xiàn)了mask 搂妻。kCGImageByteOrderMask? ? = 0x7000,?
二進制是00000111000000000000 ?
kCGImageByteOrder16Little 是00000001000000000000
寫到這里應該很明顯了蒙保。kCGImageByteOrderMask 就是規(guī)定CGImageByteOrderInfo 用的哪些位置的值辕棚。將其他位置的值給過濾掉
這里出現(xiàn)了好多alpha通道的枚舉
alpha的兩種類型,直通和預乘:
帶alpha的圖片有兩種計算方法邓厕,一種叫做直通alpha(straightalpha)逝嚎,一種叫做預乘alpha(premultipliedalpha)。這兩種類型在AE軟件里是市場可以看到的详恼,當你導入一張帶通道的圖片补君,比如說TGA,AE就會問你昧互,這張圖的alpha是怎么來的挽铁,是直通類型還是預乘類型伟桅。
這兩種類型的唯一區(qū)別在于,直通alpha圖片保留最原本的RGB數(shù)值叽掘;而預乘alpha楣铁,是原本的RGB信息乘以alpha的數(shù)值以后得到的結果(預乘意思就是預先乘以alpha)。
Premultiplied 明白這個意思就夠了更扁。
kCGImageAlphaPremultipliedLast 預乘 alpha 通道在最后面RGBA?
kCGImageAlphaPremultipliedFirst 預乘 alpha 通道在最前面 ARGB?
kCGImageAlphaLast 普通的RGBA 盖腕,沒有預乘
kCGImageAlphaFirst 普通的ARGB,沒有預乘
還有幾種形式
kCGImageAlphaNoneSkipLast, /* For example, RBGX. */沒有a通道
kCGImageAlphaNoneSkipFirst,? ? ? /* For example, XRGB. */
kCGImageAlphaOnly ?/* No color data, alpha data only */
12.CGBitmapInfo 采用的是kCGImageAlphaPremultipliedFirst 預乘 ARGB浓镜,顏色空間是rgb
13.獲取bitmap的context
14 draw image?
15.獲取image
16 保存image 到數(shù)組中溃列。
17 生成gif image
這個函數(shù)講解完畢了,總結下
1.這個函數(shù)主要是將gif 圖片轉換成可以識別的image動圖格式
2.根據(jù)每個動圖的間隔時間計算出最小間隔時間間隔膛薛,兩張圖片的時間間隔用最小間隔時間*次數(shù)標示听隐,動畫數(shù)組中添加次數(shù)個image圖片
3.將gif 圖片轉換成bitmap圖片。
4.這里用的數(shù)學方式找最大公約數(shù)
+ (BOOL)isAnimatedGIFData:(NSData *)data
大神在這個里面提供了一個網址https://www.w3.org/Graphics/GIF/spec-gif89a.txt
這里判斷gif的方式是
UInt32 magic = *(UInt32 *)data.bytes;
// http://www.w3.org/Graphics/GIF/spec-gif89a.txt
if ((magic & 0xFFFFFF) != '\0FIG') return NO;
這里注意哄啄,UInt32 是和data數(shù)據(jù)方向相反的?
gif數(shù)據(jù)的前三位是 474946
而UInt32 magic = *(UInt32 *)data.bytes; magic 的值是0xXX464947 遵绰,這是因為讀取數(shù)據(jù)都是從頭按照字節(jié)讀取的,先讀取47 放入magic的最低位增淹,再讀取49放入第二位椿访,最后46放入第三位
接下來判斷是否能轉換成source 并且gif 是否只有一張圖
沒有souce或者count不大于1都默認為不是gif
+ (BOOL)isAnimatedGIFFile:(NSString *)path
文件讀取是不是gif 不過這里沒有判斷,count和source 是否含有而只是通過FiLE指針獲取特定位置虑润,這樣也是節(jié)省開支效率吧
+ (UIImage *)imageWithPDF:(id)dataOrPath
+ (UIImage *)imageWithPDF:(id)dataOrPath size:(CGSize)size
+ (UIImage *)_yy_imageWithPDF:(id)dataOrPath resize:(BOOL)resize size:(CGSize)size
?{
CGPDFDocumentRef pdf = NULL;
if ([dataOrPath isKindOfClass:[NSData class]]) {
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)dataOrPath);
pdf = CGPDFDocumentCreateWithProvider(provider);
CGDataProviderRelease(provider);
} else if ([dataOrPath isKindOfClass:[NSString class]]) {
pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:dataOrPath]);
}
if (!pdf) return nil;
CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
if (!page) {
CGPDFDocumentRelease(pdf);
return nil;
}
CGRect pdfRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
CGSize pdfSize = resize ? size : pdfRect.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(NULL, pdfSize.width * scale, pdfSize.height * scale, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
if (!ctx) {
CGColorSpaceRelease(colorSpace);
CGPDFDocumentRelease(pdf);
return nil;
}
CGContextScaleCTM(ctx, scale, scale);
CGContextTranslateCTM(ctx, -pdfRect.origin.x, -pdfRect.origin.y);
CGContextDrawPDFPage(ctx, page);
CGPDFDocumentRelease(pdf);
CGImageRef image = CGBitmapContextCreateImage(ctx);
UIImage *pdfImage = [[UIImage alloc] initWithCGImage:image scale:scale orientation:UIImageOrientationUp];
CGImageRelease(image);
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
return pdfImage;
}
放在一起看成玫,最后都是調用最后這個函數(shù)
1.生成CGPDFDocumentRef 對象
2.獲取pdf 頁數(shù)
3.獲取每頁的大小
4.檢查是否需要重新設置大小
5創(chuàng)建bitmap context?
6 下面就是context 的矩陣轉換了
7將 page 花在context上
8從bitmap context 獲取 image
沒什么難點。簡單介紹
就是講pdf 轉換成image
+ (UIImage *)imageWithEmoji:(NSString *)emoji size:(CGFloat)size {
if (emoji.length == 0) return nil;
if (size < 1) return nil;
CGFloat scale = [UIScreen mainScreen].scale;
CTFontRef font = CTFontCreateWithName(CFSTR("AppleColorEmoji"), size * scale, NULL);
if (!font) return nil;
NSAttributedString *str = [[NSAttributedString alloc] initWithString:emoji attributes:@{ (__bridge id)kCTFontAttributeName:(__bridge id)font, (__bridge id)kCTForegroundColorAttributeName:(__bridge id)[UIColor whiteColor].CGColor }];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(NULL, size * scale, size * scale, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
CTLineRef line = CTLineCreateWithAttributedString((__bridge CFTypeRef)str);
CGRect bounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsUseGlyphPathBounds);
CGContextSetTextPosition(ctx, 0, -bounds.origin.y);
CTLineDraw(line, ctx);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
CFRelease(font);
CGColorSpaceRelease(colorSpace);
CGContextRelease(ctx);
if (line)CFRelease(line);
if (imageRef) CFRelease(imageRef);
return image;
}
將emoji 轉換成圖片
蘋果的emoji表情字體 名字是AppleColorEmoji
1.根據(jù)屏幕創(chuàng)建字體
2創(chuàng)建屬性字符串
3.創(chuàng)建bitmap圖片
4通過處理獲取emoji圖片大小?kCTLineBoundsUseGlyphPathBounds ?
1.字符(Character)和字形(Glyphs)
排版系統(tǒng)中文本顯示的一個重要的過程就是字符到字形的轉換拳喻,字符是信息本身的元素哭当,而字形是字符的圖形表征,字符還會有其它表征比如發(fā)音冗澈。 字符在計算機中其實就是一個編碼钦勘,某個字符集中的編碼,比如Unicode字符集亚亲,就囊括了大都數(shù)存在的字符彻采。 而字形則是圖形,一般都存儲在字體文件中捌归,字形也有它的編碼肛响,也就是它在字體中的索引。 一個字符可以對應多個字形
這里獲取的是字形
5.獲取image
+ (UIImage *)imageWithColor:(UIColor *)color
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
通過color 獲取image 老生常談的問題了惜索。不做說明
+ (UIImage *)imageWithSize:(CGSize)size drawBlock:(void (^)(CGContextRef context))drawBlock {
if (!drawBlock) return nil;
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
if (!context) return nil;
drawBlock(context);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
這里主要是回調一個context 可以自定義繪制內容
- (BOOL)hasAlphaChannel
是否有alpha通道
- (void)drawInRect:(CGRect)rect withContentMode:(UIViewContentMode)contentMode clipsToBounds:(BOOL)clips
看這個函數(shù)我們先看看
1根據(jù)contentMode ?獲取rect
2根據(jù)是否clip 進行drawInRect
- (UIImage *)imageByResizeToSize:(CGSize)size
重新設置image 大小
- (UIImage *)imageByResizeToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode
重設大小 根據(jù)模式
- (UIImage *)imageByCropToRect:(CGRect)rect
設置修剪圖片的到rect
這里有個函數(shù)是CGImageCreateWithImageInRect 特笋。
If W and H are the width and height of image, respectively, then the
point (0,0) corresponds to the first pixel of the image data; the point
(W-1, 0) is the last pixel of the first row of the image data; (0, H-1)
is the first pixel of the last row of the image data; and (W-1, H-1) is
the last pixel of the last row of the image data.
這個是按照像素一行一行的在rect排列的。把一行超出去的都舍棄掉巾兆。相當于裁剪圖片猎物。
- (UIImage *)imageByInsetEdge:(UIEdgeInsets)insets withColor:(UIColor *)color
這個函數(shù)就是給image增加一個UIEdgeInsets 邊緣虎囚,圖片壓縮,邊框邊緣顏色是傳入的顏色蔫磨。
這里有個CGContextEOFillPath 填充規(guī)則溜宽。網上很多。自己查閱
- (UIImage *)imageByRoundCornerRadius:(CGFloat)radius
- (UIImage *)imageByRoundCornerRadius:(CGFloat)radius borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor
- (UIImage *)imageByRoundCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor borderLineJoin:(CGLineJoin)borderLineJoin
這里有個枚舉UIRectCorner 枚舉 质帅。枚舉的是矩形的四個角
這個方法就是采用UIBezierPath 進行rect繪制适揉。將圖片放入其中
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)];
可以自定義繪制圓角的位置。
這里內容不難理解煤惩。只是要自己繪制效果看看即可嫉嘀。
- (UIImage *)imageByRotate:(CGFloat)radians fitSize:(BOOL)fitSize
- (UIImage *)_yy_flipHorizontal:(BOOL)horizontal vertical:(BOOL)vertical
這個函數(shù)vImageVerticalReflect_ARGB8888 這個是垂直翻轉像素鬼悠,相當于倒立
vImageHorizontalReflect_ARGB8888 水平翻轉像素上岗。相當于照鏡子
這個函數(shù)就是是否設置圖像翻轉,上下翻轉或者左右翻轉
- (UIImage *)imageByRotateLeft90?
左旋轉90度
- (UIImage *)imageByRotateRight90
右旋轉90度
- (UIImage *)imageByRotate180?
旋轉180
- (UIImage *)imageByFlipVertical
- (UIImage *)imageByFlipHorizontal
垂直或者水平旋轉
- (UIImage *)imageByTintColor:(UIColor *)color
填充顏色
- (UIImage *)imageByGrayscale
- (UIImage *)imageByBlurSoft
- (UIImage *)imageByBlurLight
- (UIImage *)imageByBlurExtraLigh
- (UIImage *)imageByBlurDark
- (UIImage *)imageByBlurWithTint:(UIColor *)tintColor
這幾個函數(shù)都是調用
- (UIImage *)imageByBlurRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor tintMode:(CGBlendMode)tintBlendMode saturation:(CGFloat)saturation maskImage:(UIImage *)maskImage
這個函數(shù)有150行音瓷,有點長洛退,我們分開看
1瓣俯。參數(shù)校驗,self 和maskImage 必須有CGImage兵怯,blueRadius 或者Saturation 必須設置彩匕。
2 判斷是否有vImageBuffer_InitWithCGImage 函數(shù)。 將imageRef 以format形式書寫到effect中媒区。而scratch 以effect的內從初始化(effect 相當于bitmap圖驼仪,effect 相當于畫布,大小和bitmap大小相同)袜漩。這里不想過多介紹這個函數(shù)绪爸。簡單明白就行了
從來沒看過vImage.Framework 框架,看這個函數(shù)比較困難宙攻,暫時放過去奠货。后期研究這個
- (UIImage *)_yy_mergeImageRef:(CGImageRef)effectCGImage
tintColor:(UIColor *)tintColor
tintBlendMode:(CGBlendMode)tintBlendMode
maskImage:(UIImage *)maskImage
opaque:(BOOL)opaque
這個函數(shù)等以后在看。
3.UIControl+YYAdd
- (void)setTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents {
if (!target || !action || !controlEvents) return;
NSSet *targets = [self allTargets];
for (id currentTarget in targets) {
NSArray *actions = [self actionsForTarget:currentTarget forControlEvent:controlEvents];
for (NSString *currentAction in actions) {
[self removeTarget:currentTarget action:NSSelectorFromString(currentAction)
forControlEvents:controlEvents];
}
}
[self addTarget:target action:action forControlEvents:controlEvents];
}
就是講target 關聯(lián)的controlevents 的action 替換掉
- (void)addBlockForControlEvents:(UIControlEvents)controlEvents
block:(void (^)(id sender))block
我認為這個方法還是很關鍵的座掘,給uicontrol 增加block的回調形式
看了很多yykit大神寫的block回調递惋,其實都是中間增加一個中間target 。給self 分類增加一個關聯(lián)引用數(shù)組雹顺,用這個數(shù)組保存這個target
這個方法同樣適用
1生成中間對象target.讓target 保存block對象
2.給UIControl 增加action 目標對象是target?
3.將target 保存在數(shù)組里
這樣UIControl 觸發(fā)時間丹墨,會調用target 的 action 。action 執(zhí)行block事件就ok了
- (void)removeAllBlocksForControlEvents:(UIControlEvents)controlEvents
這個就是add 的逆向寫法 不做介紹了
- (void)setBlockForControlEvents:(UIControlEvents)controlEvents
block:(void (^)(id sender))block
1removeBlock?
2增加block
這里有個枚舉UIControlEventAllEvents 嬉愧。值是0xFFFFFFFF ,相當于mask 喉前。所有事件&UIControlEventAllEvents 都是true没酣。
4.UIBarButtonItem+YYAdd
- (void)setActionBlock:(void (^)(id sender))block
增加UIBarButtonItem 的block形式王财。封裝和UIControl 一樣。不做介紹
5.UIGestureRecognizer+YYAdd
- (void)addActionBlock:(void (^)(id sender))block
這個UIGestureRecognizer 也是單純的增加了block回調的形式裕便。封裝和UIControl一樣的手法绒净。不做介紹
6.UIView+YYAdd
- (UIImage *)snapshotImage
截圖UIView
- (UIImage *)snapshotImageAfterScreenUpdates:(BOOL)afterUpdates
這個方法是對- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates 方法的封裝
afterUpdates
A Boolean value that indicates whether the snapshot should be rendered after recent changes have been incorporated. Specify the valueNOif you want to render a snapshot in the view hierarchy’s current state, which might not include recent changes.
這里發(fā)現(xiàn)一篇文章,講述截圖的偿衰。地址挂疆。沒仔細看,后期寫完回去再看看這里的具體實現(xiàn)細節(jié)下翎。
- (NSData *)snapshotPDF
渲染成pdf
- (void)setLayerShadow:(UIColor*)color offset:(CGSize)offset radius:(CGFloat)radius
layer 陰影設置
shadowOpacity ?陰影的透明度缤言,默認是0 ? 范圍 0-1 越大越不透明
shouldRasterize設成true時,layer被渲染成一個bitmap视事,并緩存起來胆萧,等下次使用時不會再重新去渲染了。
shouldRasterize
實現(xiàn)組透明的效果俐东,如果它被設置為YES跌穗,在應用透明度之前,圖層及其子圖層都會被整合成一個整體的圖片虏辫,這樣就沒有透明度混合的問題了;
為了啟用shouldRasterize屬性蚌吸,我們設置了圖層的rasterizationScale屬性。默認情況下砌庄,所有圖層拉伸都是1.0套利, 所以如果你使用了shouldRasterize屬性,你就要確保你設置了rasterizationScale屬性去匹配屏幕鹤耍,以防止出現(xiàn)Retina屏幕像素化的問題肉迫。
這里知識點挺多的,與性能有關系稿黄。沒有仔細看的文章地址?地址2
- (void)removeAllSubviews
刪除subview
- (UIViewController *)viewController {
for (UIView *view = self; view; view = view.superview) {
UIResponder *nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
}
return nil;
}
查找view 的頂層控制器喊衫。 為啥這么寫,其實我們要了解響應鏈杆怕。
事件響應鏈:當用戶點擊一個UIView時族购,系統(tǒng)會產生一個事件,并將其放入UIApplication的事件隊列中陵珍。然后該事件會順著這條鏈傳遞到用戶點擊的那個UIView:UIApplication->UIWindow->RootView->...->Subview寝杖。然后開始處理這個事件,若Subview不處理互纯,事件將會傳遞給其?視圖控制器瑟幕,若沒有控制器則傳給其superView,最后傳給UIWindow,UIApplication。若UIApplication還是沒處理則將事件傳給nil只盹。
UIResponder具有nextResponder屬性,也就是其SuperView或是UIViewConterller等辣往。UIView是UIResponder的子類,所以UIView及其子類都能使用此屬性殖卑。
- (CGFloat)visibleAlpha
可視透明度站削。UIView 遍歷到最后的根都是UIWindow
這里用了透明度的累積
- (CGPoint)convertPoint:(CGPoint)point toViewOrWindow:(UIView *)view
- (CGPoint)convertPoint:(CGPoint)point fromViewOrWindow:(UIView *)view
- (CGRect)convertRect:(CGRect)rect toViewOrWindow:(UIView *)view
- (CGRect)convertRect:(CGRect)rect fromViewOrWindow:(UIView *)view
坐標轉換 。
- (CGFloat)left
- (void)setLeft:(CGFloat)x
- (CGFloat)top
- (void)setTop:(CGFloat)y
- (CGFloat)right
- (void)setRight:(CGFloat)right
- (CGFloat)bottom
- (void)setBottom:(CGFloat)bottom
- (CGFloat)width
- (void)setWidth:(CGFloat)width
- (CGFloat)height
- (void)setHeight:(CGFloat)height
- (CGFloat)centerX
- (void)setCenterX:(CGFloat)centerX
- (CGFloat)centerY
- (void)setCenterY:(CGFloat)centerY
- (CGPoint)origin
- (void)setOrigin:(CGPoint)origin
- (CGSize)size
- (void)setSize:(CGSize)size
7.UIScrollView+YYAdd
- (void)scrollToTop
- (void)scrollToBottom
- (void)scrollToLeft
- (void)scrollToRight
簡單的封裝孵稽。
8.UITableView+YYAdd
- (void)updateWithBlock:(void (^)(UITableView *tableView))block
更新tableview?
- (void)scrollToRow:(NSUInteger)row inSection:(NSUInteger)section atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
滾動到row
- (void)insertRowAtIndexPath:(NSIndexPath *)indexPath withRowAnimation:(UITableViewRowAnimation)animation
增加row
- (void)insertRow:(NSUInteger)row inSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
同上
- (void)reloadRowAtIndexPath:(NSIndexPath *)indexPath withRowAnimation:(UITableViewRowAnimation)animation
刷新row
- (void)reloadRow:(NSUInteger)row inSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
同上
- (void)deleteRowAtIndexPath:(NSIndexPath *)indexPath withRowAnimation:(UITableViewRowAnimation)animation
刪除row
- (void)deleteRow:(NSUInteger)row inSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
同上
- (void)insertSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
- (void)deleteSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
- (void)reloadSection:(NSUInteger)section withRowAnimation:(UITableViewRowAnimation)animation
對section 的增刪 更新
- (void)clearSelectedRowsAnimated:(BOOL)animated
清除選中的row
9.UITextField+YYAdd
- (void)selectAllText
選中所有文本
- (void)setSelectedRange:(NSRange)range?
選中特定范圍文本
10.UIScreen+YYAdd
+ (CGFloat)screenScale
獲取screen scale
- (CGRect)currentBounds
獲取screen bound 豎屏的bounds
- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation
返回豎屏的bounds
- (CGSize)sizeInPixel
獲取屏幕像素點大小
- (CGFloat)pixelsPerInch?
獲取單位長度的像素點
這里了解ppi 公式是
以iphone3gs分辨率為480*320為例
可以看看這個博客许起。這樣的博客很多,可以自行查閱
11.UIDevice+YYAdd
+ (double)systemVersion
獲取系統(tǒng)版本
- (BOOL)isPad
判斷是否是ipad
- (BOOL)isJailbroken
檢查是否越獄菩鲜,由于沒有想過經歷园细,不做深究。
- (BOOL)canMakePhoneCalls
是否能打電話
- (NSString *)ipAddressWithIfaName:(NSString *)name
getifaddrs 獲取本機地址
判斷ifaName 的ip地址字符串
.把ip地址轉化為用于網絡傳輸?shù)亩M制數(shù)值
int inet_aton(const char *cp, struct in_addr *inp);
inet_aton() 轉換網絡主機地址ip(如192.168.1.10)為二進制數(shù)值睦袖,并存儲在struct in_addr結構中珊肃,即第二個參數(shù)*inp,函數(shù)返回非0表示cp主機有地有效,返回0表示主機地址無效馅笙。(這個轉換完后不能用于網絡傳輸伦乔,還需要調用htons或htonl函數(shù)才能將主機字節(jié)順序轉化為網絡字節(jié)順序)
in_addr_t inet_addr(const char *cp);
inet_addr函數(shù)轉換網絡主機地址(如192.168.1.10)為網絡字節(jié)序二進制值,如果參數(shù)char *cp無效董习,函數(shù)返回-1(INADDR_NONE),這個函數(shù)在處理地址為255.255.255.255時也返回-1,255.255.255.255是一個有效的地址烈和,不過inet_addr無法處理;
- (NSString *)ipAddressWIFI
檢查ip地址是否是wifi
- (NSString *)ipAddressCell
檢查ip地址是否是蜂窩
- (uint64_t)getNetworkTrafficBytes:(YYNetworkTrafficType)types
這里先看自定義的YYNetworkTrafficType
typedef NS_OPTIONS(NSUInteger, YYNetworkTrafficType) {
YYNetworkTrafficTypeWWANSent? ? = 1 << 0,
YYNetworkTrafficTypeWWANReceived = 1 << 1,
YYNetworkTrafficTypeWIFISent? ? = 1 << 2,
YYNetworkTrafficTypeWIFIReceived = 1 << 3,
YYNetworkTrafficTypeAWDLSent? ? = 1 << 4,
YYNetworkTrafficTypeAWDLReceived = 1 << 5,
YYNetworkTrafficTypeWWAN = YYNetworkTrafficTypeWWANSent | YYNetworkTrafficTypeWWANReceived,
YYNetworkTrafficTypeWIFI = YYNetworkTrafficTypeWIFISent | YYNetworkTrafficTypeWIFIReceived,
YYNetworkTrafficTypeAWDL = YYNetworkTrafficTypeAWDLSent | YYNetworkTrafficTypeAWDLReceived,
YYNetworkTrafficTypeALL = YYNetworkTrafficTypeWWAN |
YYNetworkTrafficTypeWIFI |
YYNetworkTrafficTypeAWDL,
};
/**
Network traffic type:
WWAN: Wireless Wide Area Network.
For example: 3G/4G.
WIFI: Wi-Fi.
AWDL: Apple Wireless Direct Link (peer-to-peer connection).
For exmaple: AirDrop, AirPlay, GameKit.
*/
這是yykit大神自己的解釋
針對wwan wifi awdl 分別定義了send 和recevice
接下來看
static yy_net_interface_counter yy_get_net_interface_counter() c函數(shù)
static yy_net_interface_counter yy_get_net_interface_counter() {
static dispatch_semaphore_t lock;
static NSMutableDictionary *sharedInCounters;
static NSMutableDictionary *sharedOutCounters;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInCounters = [NSMutableDictionary new];
sharedOutCounters = [NSMutableDictionary new];
lock = dispatch_semaphore_create(1);
});
yy_net_interface_counter counter = {0};
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
if (getifaddrs(&addrs) == 0) {
cursor = addrs;
dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
while (cursor) {
if (cursor->ifa_addr->sa_family == AF_LINK) {
const struct if_data *data = cursor->ifa_data;
NSString *name = cursor->ifa_name ? [NSString stringWithUTF8String:cursor->ifa_name] : nil;
if (name) {
uint64_t counter_in = ((NSNumber *)sharedInCounters[name]).unsignedLongLongValue;
counter_in = yy_net_counter_add(counter_in, data->ifi_ibytes);
sharedInCounters[name] = @(counter_in);
uint64_t counter_out = ((NSNumber *)sharedOutCounters[name]).unsignedLongLongValue;
counter_out = yy_net_counter_add(counter_out, data->ifi_obytes);
sharedOutCounters[name] = @(counter_out);
if ([name hasPrefix:@"en"]) {
counter.en_in += counter_in;
counter.en_out += counter_out;
} else if ([name hasPrefix:@"awdl"]) {
counter.awdl_in += counter_in;
counter.awdl_out += counter_out;
} else if ([name hasPrefix:@"pdp_ip"]) {
counter.pdp_ip_in += counter_in;
counter.pdp_ip_out += counter_out;
}
}
}
cursor = cursor->ifa_next;
}
dispatch_semaphore_signal(lock);
freeifaddrs(addrs);
}
return counter;
}
1.創(chuàng)建一個信號量鎖dispatch_semaphore_t 初始化一些變量
2.初始化yy_net_interface_counter 結構體
typedef struct {
uint64_t en_in;
uint64_t en_out;
uint64_t pdp_ip_in;
uint64_t pdp_ip_out;
uint64_t awdl_in;
uint64_t awdl_out;
} yy_net_interface_counter;
en 代表ip地址
pdp 代表我們使用的cell
awdl代表?Apple Wireless Direct Link
3.循環(huán)讀取ip地址?
這里代表AF_LINK 鏈路層接口
我用模擬器打印了這個函數(shù)的返回的部分信息
NSString *name = cursor->ifa_name ? [NSString stringWithUTF8String:cursor->ifa_name] : @"nil";
NSLog(@"%d name:%@",cursor->ifa_addr->sa_family,name);
2017-12-20 11:12:16.218952+0800 YYKitDemo[25918:11075457] 18 name:lo0
2017-12-20 11:12:16.219145+0800 YYKitDemo[25918:11075457] 2 name:lo0
2017-12-20 11:12:16.219377+0800 YYKitDemo[25918:11075457] 30 name:lo0
2017-12-20 11:12:16.219560+0800 YYKitDemo[25918:11075457] 30 name:lo0
2017-12-20 11:12:16.219693+0800 YYKitDemo[25918:11075457] 18 name:gif0
2017-12-20 11:12:16.219798+0800 YYKitDemo[25918:11075457] 18 name:stf0
2017-12-20 11:12:16.220025+0800 YYKitDemo[25918:11075457] 18 name:XHC20
2017-12-20 11:12:16.220134+0800 YYKitDemo[25918:11075457] 18 name:en0
2017-12-20 11:12:16.220254+0800 YYKitDemo[25918:11075457] 30 name:en0
2017-12-20 11:12:16.220356+0800 YYKitDemo[25918:11075457] 2 name:en0
2017-12-20 11:12:16.220689+0800 YYKitDemo[25918:11075457] 18 name:p2p0
2017-12-20 11:12:16.220869+0800 YYKitDemo[25918:11075457] 18 name:awdl0
2017-12-20 11:12:16.221108+0800 YYKitDemo[25918:11075457] 30 name:awdl0
2017-12-20 11:12:16.221408+0800 YYKitDemo[25918:11075457] 18 name:en1
2017-12-20 11:12:16.221628+0800 YYKitDemo[25918:11075457] 18 name:en2
2017-12-20 11:12:16.221955+0800 YYKitDemo[25918:11075457] 18 name:bridge0
2017-12-20 11:12:16.222193+0800 YYKitDemo[25918:11075457] 18 name:utun0
2017-12-20 11:12:16.222497+0800 YYKitDemo[25918:11075457] 30 name:utun0
#define AF_LINK 18?#define AF_INET 2?#define AF_INET6 30 ?
可以看出來,AF_lINK 包含了?AF_INET ?AF_INET6 是所有連接的都會返回來
這里調用c函數(shù)
static uint64_t yy_net_counter_add(uint64_t counter, uint64_t bytes) {
if (bytes < (counter % 0xFFFFFFFF)) {
counter += 0xFFFFFFFF - (counter % 0xFFFFFFFF);
counter += bytes;
} else {
counter = bytes;
}
return counter;
}
如果bytes 比counter 取模小 皿淋,那么我就將counter 的前面32 位置0招刹,而高位加1,再加上bytes窝趣。(沒看懂)
要是比counter取模大疯暑,直接賦值。
4用counter 記錄結果
5 獲取網絡字節(jié)數(shù)
- (NSString *)machineModel
獲取設備model
還有一種方法
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
不知道這兩種獲取方式有啥不同
- (NSString *)machineModelName
獲取設備model 字符串
- (NSDate *)systemUptime?
系統(tǒng)開機時間
- (int64_t)diskSpace
磁盤空間
- (int64_t)diskSpaceFree
磁盤剩余空間
- (int64_t)diskSpaceUsed
用戶使用空間
- (int64_t)memoryTotal
內存大小
- (int64_t)memoryUsed
使用的內存大小
- (int64_t)memoryFree
剩余內存大小
- (int64_t)memoryActive?
激活內存大小
- (int64_t)memoryInactive
未激活內存大小
- (int64_t)memoryWired
- (int64_t)memoryPurgable
- (NSUInteger)cpuCount
cpu數(shù)量
- (float)cpuUsage
cpu 使用的比例
- (NSArray *)cpuUsagePerProcessor
每個processor中cpu的使用比例
這部分內存獲取查閱資料很少哑舒,暫時不做深究妇拯。
12.UIApplication+YYAdd
- (NSURL *)documentsURL
- (NSString *)documentsPath
獲取document 文件路徑或者url
- (NSURL *)cachesURL
- (NSString *)cachesPath
獲取caches 文件路徑或者url
- (NSURL *)libraryURL
- (NSString *)libraryPath
獲取library文件路徑或者url
- (BOOL)isPirated
檢查是否是盜版的?
- (BOOL)_yy_fileExistInMainBundle:(NSString *)name
檢查文件是否存在
- (NSString *)appBundleName
獲取bundleName
- (NSString *)appBundleID
獲取bundleId
- (NSString *)appVersion
獲取app版本
- (NSString *)appBuildVersion
build版本
- (BOOL)isBeingDebugged
是否是debug模式
- (int64_t)memoryUsage
- (float)cpuUsage
- (void)incrementNetworkActivityCount
- (void)decrementNetworkActivityCount
+ (BOOL)isAppExtension
是否是app的extension
+ (UIApplication *)sharedExtensionApplication
13.UIFont+YYAdd
- (BOOL)isBold?
粗體
- (BOOL)isItalic
斜體
- (BOOL)isMonoSpace
MonoSpace?
- (BOOL)isColorGlyphs
- (CGFloat)fontWeight
字體大小
- (UIFont *)fontWithBold
轉換成粗體
- (UIFont *)fontWithItalic
轉換成斜體
- (UIFont *)fontWithBoldItalic
轉換成粗斜體
- (UIFont *)fontWithNormal
正常字體
+ (UIFont *)fontWithCTFont:(CTFontRef)CTFont
將CT轉換成UIFont
+ (UIFont *)fontWithCGFont:(CGFontRef)CGFont size:(CGFloat)size
將cgFont 轉換成UIFont
- (CTFontRef)CTFontRef CF_RETURNS_RETAINED
轉換成CTFont
CF_RETURNS_NOT_RETAINED ? 讓編譯器幫助我們管理內存
- (CGFontRef)CGFontRef CF_RETURNS_RETAINED
轉換成CGFont
+ (BOOL)loadFontFromPath:(NSString *)path
加載字體路徑
+ (void)unloadFontFromPath:(NSString *)path
自定義字體卸載
這里只介紹了自己的加載和卸載。具體自定義字體詳查資料
+ (UIFont *)loadFontFromData:(NSData *)data
獲取自定義字體
+ (BOOL)unloadFontFromData:(UIFont *)font
卸載字體
+ (NSData *)dataFromFont:(UIFont *)font
將字體轉換成data
14.UIBezierPath+YYAdd
+ (UIBezierPath *)bezierPathWithText:(NSString *)text font:(UIFont *)font?
獲取字體的bezierPath
1就是將text 換著NSAttributedString?
2獲取CTLine?
3 再獲取CTRun
4 再從CTRun中獲取每個字的path
這個文件夾的東西都是功能類洗鸵。大多數(shù)不難越锈,過于簡單的不做介紹了。