如何禁止某个类调用某些方法
@interface YYImageEncoder : NSObject
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
@end
// - 实现 不可以直接调用 init 方法 可以调用 initWithType: 并且在initWithType中调用的是 [super init];
- (instancetype)init {
@throw [NSException exceptionWithName:@"YYImageEncoder init error" reason:@"YYImageEncoder must be initialized with a type. Use 'initWithType:' instead." userInfo:nil];
return nil;
}
- (instancetype)initWithType:(YYImageType)type {
self = [super init];
if (!self) return nil;
return self;
}
解析 CGBitmapInfo
请先阅读 谈谈 iOS 中图片的解压缩
CGBitmapInfo : alpha 的信息 | 颜色分量是否为浮点数 | 像素格式的字节顺序 (用这三个数据来表示CGBitmapInfo)
-
alpha 的信息 :
-
是否有 alpha 信息
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
BOOL hasAlpha = NO;
if (alphaInfo == kCGImageAlphaPremultipliedLast ||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
alphaInfo == kCGImageAlphaFirst ||
alphaInfo == kCGImageAlphaLast) {
hasAlpha = YES;
} -
如果包含 alpha ,那么 alpha 信息所处的位置,在像素的最低有效位,比如 RGBA ,还是最高有效位,比如 ARGB ;
如果包含 alpha ,那么每个颜色分量是否已经乘以 alpha 的值,这种做法可以加速图片的渲染时间,因为它避免了渲染时的额外乘法运算。比如,对于 RGB 颜色空间,用已经乘以 alpha 的数据来渲染图片,每个像素都可以避免 3 次乘法运算,红色乘以 alpha ,绿色乘以 alpha 和蓝色乘以 alpha
CGImageAlphaInfo info = (hasAlpah) ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
-
-
至于颜色分量是否为浮点数,这个就比较简单了,直接逻辑或 kCGBitmapFloatComponents 就可以了; 我们一般用不上这个值
-
们知道字节顺序的值应该使用的是 32 位的主机字节顺序 kCGBitmapByteOrder32Host ,这样的话不管当前设备采用的是小端模式还是大端模式,字节顺序始终与其保持一致。
[代码]
CGImageRef imageRef = img.CGImage;
size_t wid = CGImageGetWidth(imageRef);
size_t hei = CGImageGetHeight(imageRef);
// - 位图是否包含透明度
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
BOOL hasAlpha = NO;
if (alphaInfo == kCGImageAlphaPremultipliedLast ||
alphaInfo == kCGImageAlphaPremultipliedFirst ||
alphaInfo == kCGImageAlphaFirst ||
alphaInfo == kCGImageAlphaLast) {
hasAlpha = YES;
}
// - 位图的字节存出顺序
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
// - 位图的透明度的信息的位置
bitmapInfo |= ((hasAlpha) ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst);
// - 色彩空间
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// - 创建图像上下文
CGContextRef context = CGBitmapContextCreate(NULL, wid, hei, 8, 0, colorSpace, bitmapInfo);
// - 将原始位图, 绘制到图形上下文;
CGContextDrawImage(context, CGRectMake(0, 0, wid, hei), imageRef);
// - 创建一个新的解压后的位图
CGImageRef newImage = CGBitmapContextCreateImage(context);
YYImage中timer 和 target 不引起循环引用的方式(使用消息转发)
// - 声明 YYWeakProxy
@interface YYWeakProxy : NSProxy
@property (nullable, nonatomic, weak, readonly) id target;
@end
// - 定义 YYWeakProxy
@implementation YYWeakProxy
+ (instancetype)proxyWithTarget:(id)target {
return [[YYWeakProxy alloc] initWithTarget:target];
}
- (id)forwardingTargetForSelector:(SEL)selector {
return _target;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
void *null = NULL;
[invocation setReturnValue:&null];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_target respondsToSelector:aSelector];
}
- (BOOL)isEqual:(id)object {
return [_target isEqual:object];
}
- (NSUInteger)hash {
return [_target hash];
}
- (Class)superclass {
return [_target superclass];
}
- (Class)class {
return [_target class];
}
- (BOOL)isKindOfClass:(Class)aClass {
return [_target isKindOfClass:aClass];
}
- (BOOL)isMemberOfClass:(Class)