ios基础篇(七)—— 矩阵操作、图形上下文栈、Quartz2D的内存管理、绘制、图片裁剪

el/2023/6/4 14:58:45

一、矩阵操作 -  仿射变换

  • 缩放 void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
  • 旋转 void CGContextRotateCTM(CGContextRef c, CGFloat angle)
  • 平移 void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)
#import "HMView.h"@implementation HMView
- (void)drawRect:(CGRect)rect
{// 1.获取上下文CGContextRef ctx = UIGraphicsGetCurrentContext();// 矩阵操作//    Current graphics state's Transformation Matrix// 旋转//    CGContextRotateCTM(ctx, M_PI_4);// 缩放//    CGContextScaleCTM(ctx, 1, 0.5);// 平移//    CGContextTranslateCTM(ctx, 150, 150);// 2.拼接路径 同时 把路径添加到上下文当中//    CGContextAddArc(ctx, 150, 150, 100, 0, 2 * M_PI, 1);//    CGContextMoveToPoint(ctx, 0, 0);//    CGContextAddLineToPoint(ctx, 300, 300);CGMutablePathRef path = CGPathCreateMutable();CGPathAddArc(path, NULL, 150, 150, 100, 0, 2 * M_PI, 1);CGPathMoveToPoint(path, NULL, 0, 0);CGPathAddLineToPoint(path, NULL, 300, 300);// 添加路径到上下文当中CGContextAddPath(ctx, path);// 设置线宽CGContextSetLineWidth(ctx, 10);// 3.渲染CGContextStrokePath(ctx);
}
@end

 二、图形上下文栈的操作

0. 图形上下文栈是什么?

每一个“图形上下文”对象都包含一个“栈”结构,这个栈结构用来存储当前图形上下文的状态信息。(每个图形上下文对象中都包含:1>“图形状态”; 2> 路径信息; 3> 输出目标)

1. 为什么要学习图形上下文栈?

1. 第一次画图后修改了颜色, 后面的图形要再恢复到原来的颜色

2. 第一次画图的时候旋转了上下文, 后面的图形不要旋转

3. 第一次画图的时候修改了线宽,线头样式等,后面画图的时候不要这些样式,要默认的样子

总结:前面绘图的时候修改了上下文,后面绘图的时候要再次使用被修改前的上下文对象

1、先绘制图形,设置颜色,线宽,旋转。

2、然后再绘制其他的图形。(其他图形默认也会使用相同的设置(颜色、线宽、旋转等))

解决:

1. 在第一次绘制图形前,保存上下文。

2. 在第二次绘制图形前,恢复上下文。

图形上下文栈的操作

将当前【图形上下文】中的“绘图状态”信息保存到“栈”中

void CGContextSaveGState(CGContextRef c) 

将栈顶的“绘图状态”出栈, 替换掉当前的“图形上下文”中的“绘图状态”

void CGContextRestoreGState(CGContextRef c)

   

三、Quartz2D的内存管理

  • 使用含有“Create”或“Copy”的函数创建的对象,使用完后必须释放,否则将导致内存泄露
  • 使用不含有“Create”或“Copy”的函数获取的对象,则不需要释放
  • 如果retain了一个对象,不再使用时,需要将其release掉
  • 可以使用Quartz 2D的函数来指定retain和release一个对象。例如,如果创建了一个CGColorSpace对象,则使用函数CGColorSpaceRetain和CGColorSpaceRelease来retain和release对象。
  • 也可以使用Core Foundation的CFRetain和CFRelease。注意不能传递NULL值给这些函数
  • 演示通过CGMutablePathRef实现绘图。通过 Product -> Analyze 来进行静态分析。

使用Path 对象时的内存管理问题:

1> 凡是遇到 retain 、 copy 、 create 出的对象, 都需要进行 release

2> 但是CGPathCreateMutable()不是 OC 方法, 所以不是调用 某个对象的 release方法

3> CGXxxxxCreate 对应的就有 CGXxxxxRelease。

4> 通过 CFRelease(任何类型);可以释放任何类型。

四、绘制“文字”

通过 UIKit 框架来绘制

  • [str drawAtPoint:]  从某一个点开始绘制
  • [str drawInRect:]  绘制到指定的区域

    

删除背景颜色 可以让阴影的地方显示 文字

  

将underlineStyleAttributeName 删掉 阴影直接消失     没有下划线参数就没有阴影 参数传为0 就没有下划线

五、绘制”图片”

UIImage *imgIcon = [UIImage imageNamed:@"002"];[imgIcon drawAtPoint:CGPointMake(20, 20)];[imgIcon drawInRect:rect];[imgIcon drawAsPatternInRect:rect];

 设置 UIView 的背景色为某个图片的屏幕效果。通过[UIColor colorWithXxxxxx:图片]来实现。

六、自定义一个 View 模拟图片框

ViewController.M

#import "ViewController.h"
#import "HMImageView.h"@interface ViewController ()@property (nonatomic, weak) HMImageView* imageView;
//@property (nonatomic, weak) UIImageView* imageView;
@end@implementation ViewController- (void)viewDidLoad
{[super viewDidLoad];HMImageView* imageView = [[HMImageView alloc] initWithImage:[UIImage imageNamed:@"me"]];self.imageView = imageView;[self.view addSubview:imageView];// -------//    HMImageView* imageView = [[HMImageView alloc] init];//    imageView.frame = CGRectMake(0, 0, 200, 200);//    imageView.image = [UIImage imageNamed:@"me"];//    self.imageView = imageView;//    [self.view addSubview:imageView];// *******//    UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me"]];//    self.imageView = imageView;//    [self.view addSubview:imageView];//    // -------//    UIImageView* imageView = [[UIImageView alloc] init];//    imageView.frame = CGRectMake(0, 0, 200, 200);//    imageView.image = [UIImage imageNamed:@"me"];//    self.imageView = imageView;//    [self.view addSubview:imageView];
}- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event
{self.imageView.image = [UIImage imageNamed:@"Press"];
}@end

HMImageView.M 

#import "HMImageView.h"@implementation HMImageView
- (instancetype)initWithImage:(UIImage*)image{self = [super initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];if (self) {self.image = image;}return self;
}
- (void)setImage:(UIImage*)image{_image = image;// 重绘[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{// 把传过来的图片绘制到屏幕上[self.image drawInRect:rect];
}
@end

设置 UIView 的背景为一张图片

1、通过[UIColor colorWithPatternImage:]实现

 2、通过绘制一张图片到 UIView 上实现

裁剪 只是裁剪上下文的显示区域  上下文本身依然存在且大小不变

七、图片裁剪

核心代码

void CGContextClip(CGContextRef c) 

将当前上下所绘制的路径裁剪出来(超出这个裁剪区域的都不能显示)

图片裁剪思路:

1》 在上下文中绘制一个要裁减的图形

2》调用void CGContextClip(CGContextRef c)进行裁剪

3》在裁剪好的上下文中再把图片绘制上去。(注意绘制图片的时候,必须绘制到已经裁剪出的图形位置,否则不显示)

在 UIView 上显示一个裁剪后的图片

1、获取 UIView 的图形上下文对象

2、在图形上下文对象上绘制一个圆形

3、执行裁剪操作(裁剪的意思是告诉系统,将来只有在被裁减出的区域内绘制的图形才会显示)

4、把图片绘制到上下文上(直接调用 UIImage 对象的绘图方法即可)

直接裁剪图片并保存

  • 1、加载要裁减的图片
  • 2、根据要裁剪的图片大小开启一个Bitmap 的图形上下文
  • 3、在这个图形上下文上绘制一个圆形(这个圆的圆心应为这个图形上下文的中心点,半径应为这个图形上下文的最短的边的一半)
  • 4、执行裁剪操作
  • 5、把图片绘制到当前的“图形上下文”中(因为这个图形上下文的大小是按照要裁减的图片的大小来创建的,所以绘图的时候直接从(0,0)开始绘制即可)
  • 6、从图形上下文中获取图片对象
  • 7、将图片对象转换为 NSData 类型UIImagePNGRepresentation(img)
  • 8、保存图片对象到目标位置(沙盒或者相册)

图片类型的图形上下文

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView* imageView;
@end@implementation ViewController
- (void)viewDidLoad{[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.
}
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event{// 开启图片类型的图形上下文UIGraphicsBeginImageContext(CGSizeMake(300, 300));// 获取当前的上下文(图片类型)CGContextRef ctx = UIGraphicsGetCurrentContext();// 拼接路径 同时 把路径添加上上下文当中CGContextMoveToPoint(ctx, 50, 50);CGContextAddLineToPoint(ctx, 100, 100);// 渲染//    CGContextStrokePath(ctx);// 通过图片类型的图形上下文 获取图片对象UIImage* image = UIGraphicsGetImageFromCurrentImageContext();// 关闭图片类型的图形上下文UIGraphicsEndImageContext();// 把获取到的图片 放到 图片框上self.imageView.image = image;
}

保存到沙盒

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView* imageView;
@end
@implementation ViewController
- (void)viewDidLoad{[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event{// 开启图片类型的图形上下文UIGraphicsBeginImageContext(CGSizeMake(300, 300));// 获取当前的上下文(图片类型)CGContextRef ctx = UIGraphicsGetCurrentContext();// 拼接路径 同时 把路径添加上上下文当中CGContextMoveToPoint(ctx, 50, 50);CGContextAddLineToPoint(ctx, 100, 100);// 渲染CGContextStrokePath(ctx);// 通过图片类型的图形上下文 获取图片对象UIImage* image = UIGraphicsGetImageFromCurrentImageContext()// 关闭图片类型的图形上下文UIGraphicsEndImageContext();// 把获取到的图片 放到 图片框上self.imageView.image = image;// 获取 doc 路径NSString* docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];// 获取文件路径NSString* filePath = [docPath stringByAppendingPathComponent:@"xx.png"];// 1.把 image 对象转化成 nsdata//    NSData* data = UIImagePNGRepresentation(image);NSData* data = UIImageJPEGRepresentation(image, 0);//     2.通过 data 的 write to file 写入到沙盒中[data writeToFile:filePath atomically:YES];
}
@end

开启图片类型的上下文 with option

 UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, [UIScreen mainscreen].scale);< == > UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, 0);
第三个参数最重要 缩放因子  传0表示不缩放 即在不同手机的不同屏幕不缩放

获取裁剪过后的图片

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView* imageView;
@end
@implementation ViewController
- (void)viewDidLoad{[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event{// 3.获取图片UIImage* image = [UIImage imageNamed:@"me"];// 1.开启图片类型的图形上下文UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);// 5.获取上下文CGContextRef ctx = UIGraphicsGetCurrentContext();// 4.画一个裁剪的图片CGContextAddArc(ctx, image.size.width * 0.5, image.size.height * 0.5, image.size.width * 0.5, 0, 2 * M_PI, 1);// 6.裁剪CGContextClip(ctx);// 7.把图片画上去[image drawAtPoint:CGPointZero];// 8.取出来UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();// 2.关闭图片类型的图形上下文UIGraphicsEndImageContext();// 测试self.imageView.image = newImage;
}
@end

获取裁剪后的图片

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView* imageView;
@end
@implementation ViewController
- (void)viewDidLoad{[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event{// 3.获取图片UIImage* image = [UIImage imageNamed:@"me"];// 1.开启图片类型的图形上下文UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);// 5.获取上下文CGContextRef ctx = UIGraphicsGetCurrentContext();// 4.画一个裁剪的图片CGContextAddArc(ctx, image.size.width * 0.5, image.size.height * 0.5, image.size.width * 0.5, 0, 2 * M_PI, 1);// 6.裁剪CGContextClip(ctx);// 7.把图片画上去[image drawAtPoint:CGPointZero];// 8.取出来UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();// 2.关闭图片类型的图形上下文UIGraphicsEndImageContext();// 测试self.imageView.image = newImage;// 保存到相册UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), @"123123123");
}
// 保存到相册的回调
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo{NSLog(@"保存完成 - %@", contextInfo);
}

裁剪一个带圆环的图片

  • // 加载要裁剪的图片    
  • // 创建一个比原始图片略大的基于 Bitmap 的“图形上下文”    
  • // 获取当前上下文    
  • // ------------------------------------ 开始绘制一个圆环    
  • / /确定圆心    

  • // 确定半径    

  • // 开始绘制圆环路径    

  • // 渲染 -------------------------------- 开始裁剪一个圆
  • // ------------------------------------ 开始绘制图片    
  • // 从绘图上下文中获取图片    
  • // 结束图形上下文    
  • // 保存到相册
  • // 保存到沙盒    
  • // 保存图片
- (void)viewDidLoad{[super viewDidLoad];// 3.获取图片UIImage* image = [UIImage imageNamed:@"me"];// 4.marginCGFloat margin = 20;// 5.计算图片类型的图形上下文的大小CGSize ctxSize = CGSizeMake(image.size.width + 2 * margin, image.size.height + 2 * margin);// 1.开启图片类型的图形上下文UIGraphicsBeginImageContextWithOptions(ctxSize, NO, 0);// 6.获取上下文CGContextRef ctx = UIGraphicsGetCurrentContext();// 8.计算圆心CGPoint arcCenter = CGPointMake(ctxSize.width * 0.5, ctxSize.height * 0.5);// 9.计算半径CGFloat radius = (image.size.width + margin) * 0.5;// 7.画圆环CGContextAddArc(ctx, arcCenter.x, arcCenter.y, radius, 0, 2 * M_PI, 1);// 10.设置宽度CGContextSetLineWidth(ctx, margin);// 11.渲染圆环CGContextStrokePath(ctx);// 12.画头像显示的区域CGContextAddArc(ctx, arcCenter.x, arcCenter.y, image.size.width * 0.5, 0, 2 * M_PI, 1);// 13.裁剪显示区域CGContextClip(ctx);// 14.画图片[image drawAtPoint:CGPointMake(margin, margin)];// 获取图片image = UIGraphicsGetImageFromCurrentImageContext();// 2.关闭图片类型的图形上下文UIGraphicsEndImageContext();// 保存到相册UIImageWriteToSavedPhotosAlbum(image, NULL, NULL, NULL);
}

图片水印

水印:在图片上加的防止他人盗图的半透明logo、文字、图标

实现方式:利用Quartz2D,将水印(文字、LOGO)画到图片的右下角

核心代码

开启一个基于位图的图形上下文

void     UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) 

从上下文中取得图片

(UIImage) UIImage* UIGraphicsGetImageFromCurrentImageContext(); 

结束基于位图的图形上下文

void     UIGraphicsEndImageContext();

图片加水印基本思路

1、添加文字水印

1> 创建位图上下文

2> 把图片画上去

3> 把文字画上去

4>  从上下文中取出图片

2、添加图片水印

1> 创建位图上下文

2> 把图片画上去

3> 加载 logo 图片(水印图片),把水印图片也画上去

4>  从上下文中取出图片

- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event{// 3.获取图片UIImage* image = [UIImage imageNamed:@"scene"];// 1.开启图片类型的图形上下文UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);// 6.画大图[image drawAtPoint:CGPointZero];// 4.文字NSString* str = @"黑马13期";// 5.画文字水印[str drawAtPoint:CGPointMake(20, 20) withAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:20] }];// 7.图片UIImage* logo = [UIImage imageNamed:@"logo"];// 8.画图片水印[logo drawAtPoint:CGPointMake(image.size.width * 0.6, image.size.height * 0.7)];// 取图片image = UIGraphicsGetImageFromCurrentImageContext();// 保存到相册UIImageWriteToSavedPhotosAlbum(image, NULL, NULL, NULL);// 2.关闭图片类型的图形上下文UIGraphicsEndImageContext();NSLog(@"test");
}

屏幕截图

核心代码

- (void)renderInContext:(CGContextRef)ctx;

调用某个view的layer的renderInContext:方法即可

截图基本思路:

1、获取控件的 layer 对象

2、调用 layer 对象的 renderInContext:方法渲染到上下文中

**注意:UISegmentedControl 渲染时有问题

- (void)viewDidLoad{// 开启图片类型的图形上下文UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);// 获取当前的上下文CGContextRef ctx = UIGraphicsGetCurrentContext();// 截图 把view 的内容 放到上下文中 然后 渲染[self.view.layer renderInContext:ctx];// 取图片UIImage* image = UIGraphicsGetImageFromCurrentImageContext();// 关闭上下文UIGraphicsEndImageContext();// 保存到相册UIImageWriteToSavedPhotosAlbum(image, NULL, NULL, NULL);
}
// --- 旋转缩放平移// 对图形上下文进行旋转平移缩放的操作// 缩放
// 第一个参数:需要缩放的上下文
// 第二个参数:x轴缩放的比例
// 第三个参数:y轴缩放的比例
CGContextScaleCTM(ctx, 1, 0.5);// 平移
// 第一个参数:需要平移的上下文
// 第二个参数:x轴的偏移量
// 第三个参数:y轴的偏移量
CGContextTranslateCTM(ctx, 150, 150);// 旋转
// 第一个参数:需要旋转的上下文
// 第二个参数:顺时针旋转的角度
CGContextRotateCTM(ctx, M_PI_4);// --- 图形上下文栈// 图形上下文栈 只是保存 状态信息(样式)// 保存状态信息
CGContextSaveGState(ctx);// 恢复状态信息
CGContextRestoreGState(ctx);// --- quartz2d 内存管理
// 如果包含 create copy 关键字的时候 记得释放
// 释放 1
CGPathRelease(path);
// 释放 2
CFRelease(path);// --- 绘制文字
// 绘制 - 从(0,0)点开始画
[str drawAtPoint:CGPointZero withAttributes:dict];// 绘制 - 绘制到指定的区域
[str drawInRect:rect withAttributes:nil];// AttributeName - key 在 UIKit下的 NSAttributeName.h 里面
// 个人建议 记其中一个// shadow
NSShadow* s = [[NSShadow alloc] init];
s.shadowOffset = CGSizeMake(100, 100); // 偏移量
s.shadowBlurRadius = 0; // 越小越不模糊 高斯模糊
s.shadowColor = [UIColor yellowColor]; // 阴影的颜色// --- 绘制图片
// 绘制 - 从某个点开始绘制
[image drawAtPoint:CGPointZero];
// 绘制 - 绘制到某一个区域
[image drawInRect:rect];
// 绘制 - 平铺
[image drawAsPatternInRect:rect]; // 可以考虑用来设置某个view的背景图片// --- 裁剪上下文显示的区域
// 前提:画一个图形
// 裁剪图片
CGContextClip(ctx);// 告诉系统 已这个图形来裁剪图片 渲染 然后显示出来
// 所谓裁剪并不是裁剪掉上下文 只是单纯的 裁剪出来希望显示的区域而已!!!// --- bitmap上下文// 创建上下文(图片)
UIGraphicsBeginImageContext(CGSizeMake(300, 300));
// 创建上下文 (大小,不透明,缩放:0)
UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0);// 关闭上下文
UIGraphicsEndImageContext();//  通过图片的图形上下文获取图片
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();// 保存到沙盒当中
NSString* path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
path = [path stringByAppendingPathComponent:@"xx.png"];
// 把image转化成 NSData类型
NSData* data = UIImagePNGRepresentation(image);
NSLog(@"%ld", data.length);
// 然后在通过data对象  write to file 来写入到沙盒中
[data writeToFile:path atomically:YES];// --- 裁剪圆形图片
// 保存到相册
// 第一个:图片
// 第二个 第三个 监听   注意:@selector 不能随便写 使用"注释"当中的方法
// 第四个: 可以把它当做一个tag来使用 参数在监听的方法当中会传入
UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), @"hello1111");// --- 屏幕截图
// 对控制器的view的layer属性 进行操作
[self.view.layer renderInContext:ctx];

 

http://www.ngui.cc/el/3419347.html

相关文章

ios基础篇(九)—— 手势识别

UIGestureRecognizer: 手势识别器 能轻松识别用户在某个view上面做的一些常见手势 UIGestureRecognizer 是一个抽象类,定义了所有手势的基本行为&#xff0c;使用它的子类才能处理具体的手势 UIPanGestureRecognizer&#xff08;拖动&#xff09; UIPinchGestureRecognizer&a…

ios基础篇(十)—— CALayer基本属性

在iOS中&#xff0c;你能看得见摸得着的东西基本上都是UIView&#xff0c;比如一个按钮、一个文本标签、一个文本输入框、一个图标等等&#xff0c;这些都是UIView其实UIView之所以能显示在屏幕上&#xff0c;完全是因为它内部的一个图层 在创建UIView对象时&#xff0c;UIView…

ios基础篇(十.一)—— 动画

CADisplayLink CADisplayLink是一种以屏幕刷新频率触发的时钟机制&#xff0c;每秒钟执行大约60次左右 CADisplayLink是一个计时器&#xff0c;可以使绘图代码与视图的刷新频率保持同步&#xff0c;而NSTimer无法确保计时器实际被触发的准确时间 使用方法&#xff1a; 定义…

ios基础篇(十一)—— 同步/异步、进程/线程、pthread、线程状态、线程同步、自动释放池

多线程 一、同步/异步 1、1同步 我们之前写程序的时候都是从上到下,从左到右,代码执行顺序1个人执行多个任务,也是依次执行&#xff0c;1个人同一时间执行1个任务 1.2异步 多个人可以同时执行多个任务 二、进程/线程 2.1进程 进程是指在系统中正在运行的一个应用程序每个…

ios基础篇(十二)—— 消息循环、GCD、任务和队列、串行、并行、Barrier阻塞、延时操作、一次性执行

一、消息循环 什么是消息循环 Runloop就是消息循环&#xff0c;每一个线程内部都有一个消息循环只有主线程的消息循环默认开启&#xff0c;子线程的消息循环默认不开启消息循环的目的 保证程序不退出负责处理输入事件如果没有事件发生&#xff0c;会让程序进入休眠状态 1.1 消…

ios基础篇(十三)—— 调度组、NSOperationQueue

一、调度组 有时候需要在多个异步任务都执行完成之后继续做某些事情&#xff0c;比如下载歌曲&#xff0c;等所有的歌曲都下载完毕之后 转到 主线程提示用户 //1 全局队列dispatch_queue_t queue dispatch_get_global_queue(0, 0);//2 调度组dispatch_group_t group dispatc…

ios基础篇(十五)—— SDWebImage

一、SDWebImage介绍 什么是SDWebImage iOS中著名的牛逼的网络图片处理框架包含的功能&#xff1a;图片下载、图片缓存、下载进度监听、gif处理等等用法极其简单&#xff0c;功能十分强大&#xff0c;大大提高了网络图片的处理效率国内超过90%的iOS项目都有它的影子项目地址 ht…

ios基础篇(十六)—— 网络之sockct

一、网络基本概念 客户端&#xff1a;应用 C/S B/S服务器&#xff1a;为客户端提供服务、数据、资源的机器请求&#xff1a;客户端向服务器索取数据响应&#xff1a;服务器对客户端的请求作出反应&#xff0c;一般是返回给客户端数据服务器 内网服务器外网服务器本地测试服…

时序图

一、时序图简介&#xff08;Brief introduction&#xff09; 时序图&#xff08;Sequence Diagram&#xff09;是显示对象之间交互的图&#xff0c;这些对象是按时间顺序排列的。 顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序。 时序图中包括的建模元素主要有&a…

《Objective-C高级编程:iOS与OS X多线程和内存管理》 一 自动引用计数

一、自动引用计数 1.1 内存管理的思考方式 对象操作与objective-c 方法的对应对象操作Object-C 方法生成并持有对象alloc、new、copy、mutableCopy持有对象retain方法释放对象release方法废弃对象dealloc方法1.1.1 自己生成的对象&#xff0c;自己持有 使用以下名称开头的方…