2019独角兽企业重金招聘Python工程师标准>>>

Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境

Quartz 2D API可以实现许多功能,如基于路径的绘图、透明度、阴影、颜色管理、反锯齿、PDF文档生成和PDF元数据访问等

Quartz 2D API是Core Graphics框架的一部分,因此其中的很多数据类型和方法都是以CG开头的。会经常见到Quartz 2D(Quartz)和Core Graphics两个术语交互使用

Quartz 2D与分辨率和设备无关,因此在使用Quartz 2D绘图时,无需考虑最终绘图的目标设备

Core Graphic框架是一组基于C的API,可以用于一切绘图操作,这个框架的重要性,仅次于UIKit和Foundation

当使用UIKit创建按钮、标签或者其他UIView的子类时,UIKit会用Core Graphics将这些元素绘制在屏幕上。此外,UIEvent(UIKit中的事件处理类)也会使用Core Graphics,用来帮助确定触摸事件在屏幕上所处的位置

因为UIKit依赖于Core Graphics,所以当引入<UIKit/Uikit.h>时,Core Graphics框架会被自动引入,即UIKit内部已经引入了Core Graphics框架的主头文件:<CoreGraphics/CoreGraphics.h>

为了让开发者不必触及底层的Core Graphics的C接口,UIKit内部封装了Core Graphics的一些API,可以快速生成通用的界面元素。但是,有时候直接利用Core Graphics的C接口是很有必要和很有好处的,比如创建一个自定义的界面元素。

Quartz 2D绘图的基本步骤:

1. 获取与视图相关联的上下文对象
UIGraphicsGetCurrentContext
2. 创建及设置路径 (path)
2.1 创建路径
2.2 设置路径起点
2.3 增加路径内容……
3. 将路径添加到上下文
4. 设置上下文状态
边线颜色、填充颜色、线宽、线段连接样式、线段首尾样式、虚线样式…
5. 绘制路径
6. 释放路径

接下来实现一个画板:

#import <Foundation/Foundation.h>@interface DrawPath : NSObject+ (id)drawPathWithCGPath:(CGPathRef)drawPathcolor:(UIColor *)colorlineWidth:(CGFloat)lineWidth;@property (strong, nonatomic) UIBezierPath *drawPath;
@property (strong, nonatomic) UIColor *drawColor;
@property (assign, nonatomic) CGFloat lineWith;// 用户选择的图像
@property (strong, nonatomic) UIImage *image;@end

#import "DrawPath.h"@implementation DrawPath+ (id)drawPathWithCGPath:(CGPathRef)drawPathcolor:(UIColor *)colorlineWidth:(CGFloat)lineWidth
{DrawPath *path = [[DrawPath alloc]init];path.drawPath = [UIBezierPath bezierPathWithCGPath:drawPath];path.drawColor = color;path.lineWith = lineWidth;return path;
}@end

#import "DrawView.h"
#import "DrawPath.h"@interface DrawView()// 当前的绘图路径
@property (assign, nonatomic) CGMutablePathRef drawPath;
// 绘图路径数组
@property (strong, nonatomic) NSMutableArray *drawPathArray;// 标示路径是否被释放
@property (assign, nonatomic) BOOL pathReleased;@end@implementation DrawView- (id)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {[self setBackgroundColor:[UIColor whiteColor]];// 设置属性的初始值self.lineWidth = 10.0;self.drawColor = [UIColor redColor];}return self;
}#pragma mark - 绘制视图
// 注意:drawRect方法每次都是完整的绘制视图中需要绘制部分的内容
- (void)drawRect:(CGRect)rect
{// 1. 获取上下文CGContextRef context = UIGraphicsGetCurrentContext();[self drawView:context];
}#pragma mark 绘图视图内容的方法
- (void)drawView:(CGContextRef)context
{// 首先将绘图数组中的路径全部绘制出来for (DrawPath *path in self.drawPathArray) {if (path.image == nil) {CGContextAddPath(context, path.drawPath.CGPath);[path.drawColor set];CGContextSetLineWidth(context, path.lineWith);CGContextSetLineCap(context, kCGLineCapRound);CGContextDrawPath(context, kCGPathStroke);} else {// 有图像,没路径
//            CGContextDrawImage(context, self.bounds, path.image.CGImage);[path.image drawInRect:self.bounds];}}//--------------------------------------------------------// 以下代码绘制当前路径的内容,就是手指还没有离开屏幕// 内存管理部分提到,所有create创建的都要release,而不能设置成NULLif (!self.pathReleased) {        // 1. 添加路径CGContextAddPath(context, self.drawPath);// 2. 设置上下文属性[self.drawColor set];CGContextSetLineWidth(context, self.lineWidth);CGContextSetLineCap(context, kCGLineCapRound);// 3. 绘制路径CGContextDrawPath(context, kCGPathStroke);}
}#pragma mark - 触摸事件
#pragma mark 触摸开始,创建绘图路径
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self];self.drawPath = CGPathCreateMutable();// 记录路径没有被释放self.pathReleased = NO;// 在路径中记录触摸的初始点CGPathMoveToPoint(self.drawPath, NULL, location.x, location.y);
}#pragma mark 移动过程中,将触摸点不断添加到绘图路径
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{// 可以获取到用户当前触摸的点UITouch *touch = [touches anyObject];CGPoint location = [touch locationInView:self];// 将触摸点添加至路径CGPathAddLineToPoint(self.drawPath, NULL, location.x, location.y);[self setNeedsDisplay];
}#pragma mark 触摸结束,释放路径
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{// 一笔画完之后,将完整的路径添加到路径数组之中// 使用数组的懒加载if (self.drawPathArray == nil) {self.drawPathArray = [NSMutableArray array];}// 要将CGPathRef添加到NSArray之中,需要借助贝塞尔曲线对象// 贝塞尔曲线是UIKit对CGPathRef的一个封装,贝塞尔路径的对象可以直接添加到数组
//    UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:self.drawPath];DrawPath *path = [DrawPath drawPathWithCGPath:self.drawPath color:self.drawColor lineWidth:self.lineWidth];// 需要记录当前绘制路径的颜色和线宽[self.drawPathArray addObject:path];CGPathRelease(self.drawPath);// 标示路径已经被释放self.pathReleased = YES;// 测试线宽的代码
//    self.lineWidth = arc4random() % 20 + 1.0;
}#pragma mark - 工具视图执行方法
- (void)undo
{// 在执行撤销操作时,当前没有绘图路径// 要做撤销操作,需要把路径数组中的最后一条路径删除[self.drawPathArray removeLastObject];[self setNeedsDisplay];
}#pragma mark - 清屏操作
- (void)clearScreen
{// 在执行清屏操作时,当前没有绘图路径// 要做清屏操作,只要把路径数组清空即可[self.drawPathArray removeAllObjects];[self setNeedsDisplay];
}#pragma mark - image 的 setter方法
- (void)setImage:(UIImage *)image
{/*目前绘图的方法:1> 用self.drawPathArray记录已经完成(抬起手指)的路径2> 用self.drawPath记录当前正在拖动中的路径绘制时,首先绘制self.drawPathArray,然后再绘制self.drawPathimage 传入时,drawPath没有被创建(被release但不是NULL)如果1> 我们将image也添加到self.drawPathArray(DrawPath)2> 在绘图时,根据是否存在image判断是绘制路径还是图像就可以实现用一个路径数组即绘制路径,又绘制图像的目的之所以要用一个数组,是因为绘图是有顺序的接下来,首先需要扩充DrawPath,使其支持image*/// 1. 实例化一个新的DrawPathDrawPath *path = [[DrawPath alloc]init];[path setImage:image];// 2. 将其添加到self.drawPathArray,数组是懒加载的if (self.drawPathArray == nil) {self.drawPathArray = [NSMutableArray array];}[self.drawPathArray addObject:path];// 3. 重绘[self setNeedsDisplay];
}@end

#import <UIKit/UIKit.h>@interface MyButton : UIButton@property (assign, nonatomic) BOOL selectedMyButton;@end
#import "MyButton.h"@implementation MyButton- (id)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {[self.titleLabel setFont:[UIFont systemFontOfSize:12.0]];[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];}return self;
}- (void)drawRect:(CGRect)rect
{// 如果selectedMyButton == YES在按钮的下方绘制一条红线if (self.selectedMyButton) {CGRect frame = CGRectMake(0, self.bounds.size.height - 2, self.bounds.size.width, 2);[[UIColor redColor]set];UIRectFill(frame);}
}#pragma mark - setter方法
- (void)setSelectedMyButton:(BOOL)selectedMyButton
{_selectedMyButton = selectedMyButton;[self setNeedsDisplay];
}@end
#import <UIKit/UIKit.h>#pragma mark - 定义块代码
typedef void(^SelectColorBlock)(UIColor *color);@interface SelectColorView : UIView// 扩展initWithFrame方法,增加块代码参数
// 该块代码,将在选择颜色按钮之后执行
- (id)initWithFrame:(CGRect)frame afterSelectColor:(SelectColorBlock)afterSelectColor;@end
#import "SelectColorView.h"#define kButtonSpace 10.0@interface SelectColorView()
{// 选择颜色的块代码变量SelectColorBlock _selectColorBlock;
}@property (strong, nonatomic) NSArray *colorArray;@end@implementation SelectColorView- (id)initWithFrame:(CGRect)frame afterSelectColor:(SelectColorBlock)afterSelectColor
{self = [super initWithFrame:frame];if (self) {_selectColorBlock = afterSelectColor;[self setBackgroundColor:[UIColor lightGrayColor]];// 绘制颜色的按钮NSArray *array = @[[UIColor darkGrayColor],[UIColor redColor],[UIColor greenColor],[UIColor blueColor],[UIColor yellowColor],[UIColor orangeColor],[UIColor purpleColor],[UIColor brownColor],[UIColor blackColor],];self.colorArray = array;[self createColorButtonsWithArray:array];}return self;
}#pragma mark - 绘制颜色按钮
- (void)createColorButtonsWithArray:(NSArray *)array
{// 1. 计算按钮的位置// 2. 设置按钮的颜色,需要使用数组// 按钮的宽度,起始点位置NSInteger count = array.count;CGFloat width = (self.bounds.size.width - (count + 1) * kButtonSpace)/ count;CGFloat height = self.bounds.size.height;NSInteger index = 0;for (NSString *text in array) {UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];CGFloat startX = kButtonSpace + index * (width + kButtonSpace);[button setFrame:CGRectMake(startX, 5, width, height - 10)];// 设置按钮的背景颜色[button setBackgroundColor:array[index]];[button setTag:index];[button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];[self addSubview:button];index++;}
}#pragma mark - 按钮监听方法
- (void)tapButton:(UIButton *)button
{// 调用块代码_selectColorBlock(self.colorArray[button.tag]);
}@end
#import <UIKit/UIKit.h>#pragma mark - 定义块代码
typedef void(^SelectLineWidthBlock)(CGFloat lineWidth);@interface SelectLineWidthView : UIView#pragma mark 扩展初始化方法,增加块代码
- (id)initWithFrame:(CGRect)frame afterSelectLineWidth:(SelectLineWidthBlock)afterSeletLineWidth;@end
#import "SelectLineWidthView.h"
// 针对不同的界面,因为按钮的数量是不同的,有时候需要调整按钮间距,保证好的视觉效果
#define kButtonSpace 10.0@interface SelectLineWidthView()
{SelectLineWidthBlock _selectLineWidthBlock;
}@property (strong, nonatomic) NSArray *lineWidthArray;@end@implementation SelectLineWidthView- (id)initWithFrame:(CGRect)frame afterSelectLineWidth:(SelectLineWidthBlock)afterSeletLineWidth
{self = [super initWithFrame:frame];if (self) {_selectLineWidthBlock = afterSeletLineWidth;[self setBackgroundColor:[UIColor redColor]];[self setBackgroundColor:[UIColor lightGrayColor]];// 绘制颜色的按钮NSArray *array = @[@(1.0), @(3.0), @(5.0), @(8.0), @(10.0), @(15.0), @(20.0)];self.lineWidthArray = array;[self createLineButtonsWithArray:array];}return self;
}#pragma mark 创建选择线宽的按钮
- (void)createLineButtonsWithArray:(NSArray *)array
{// 1. 计算按钮的位置// 2. 设置按钮的颜色,需要使用数组// 按钮的宽度,起始点位置NSInteger count = array.count;CGFloat width = (self.bounds.size.width - (count + 1) * kButtonSpace)/ count;CGFloat height = self.bounds.size.height;NSInteger index = 0;for (NSString *text in array) {UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];CGFloat startX = kButtonSpace + index * (width + kButtonSpace);[button setFrame:CGRectMake(startX, 5, width, height - 10)];// 设置选择线宽的提示文字NSString *text = [NSString stringWithFormat:@"%@点", self.lineWidthArray[index]];[button setTitle:text forState:UIControlStateNormal];[button.titleLabel setFont:[UIFont systemFontOfSize:15]];[button setTag:index];[button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];[self addSubview:button];index++;}
}#pragma mark - 按钮监听方法
- (void)tapButton:(UIButton *)button
{// 把按钮对应的线宽数值作为块代码的参数,执行块代码_selectLineWidthBlock([self.lineWidthArray[button.tag]floatValue]);
}@end
#import <UIKit/UIKit.h>
#import "SelectColorView.h"
#import "SelectLineWidthView.h"#pragma mark 工具视图的操作块代码
typedef void(^ToolViewActionBlock)();//#pragma mark - 选择橡皮擦的块代码定义
//typedef void(^ToolViewSelectEarserBlock)();
//#pragma mark - 选择撤销操作的块代码
//typedef void(^ToolViewSelectUndoBlock)();
//#pragma mark - 选择清屏操作的块代码
//typedef void(^ToolViewSelectClearBlock) ();
//#pragma mark - 选择相机的块代码
//typedef void(^ToolViewSelectPhotoBlock) ();@interface ToolView : UIView// 对initWithFrame进行扩展,增加块代码参数
- (id)initWithFrame:(CGRect)frame
afterSelectColor:(SelectColorBlock)afterSelectColor
afterSelectLineWidth:(SelectLineWidthBlock)afterSelectLineWidthselectEarser:(ToolViewActionBlock)selectEarserseletUndo:(ToolViewActionBlock)selectUndoselectClear:(ToolViewActionBlock)selectClearselectPhoto:(ToolViewActionBlock)selectPhoto;@end
#import "ToolView.h"
#import "MyButton.h"// 按钮的间距
#define kButtonSpace 10.0// 注意,枚举的顺序需要和按钮文字数组中的顺序保持一致
typedef enum
{kButtonColor = 0,kButtonLineWidth,kButtonEarser,kButtonUndo,kButtonClearScreen,kButtonCamera,kButtonSave
} kButtonActionType;@interface ToolView()
{SelectColorBlock _selectColorBlock;SelectLineWidthBlock _selectLineWidthBlock;ToolViewActionBlock _selectEarserBlock;ToolViewActionBlock _selectUndoBlock;ToolViewActionBlock _selectClearBlock;ToolViewActionBlock _selectPhotoBlock;
}// 当前用户选中的按钮
@property (weak, nonatomic) MyButton *selectButton;
// 选择颜色视图
@property (weak, nonatomic) SelectColorView *colorView;
// 选择线宽视图
@property (weak, nonatomic) SelectLineWidthView *lineWidthView;@end@implementation ToolView- (id)initWithFrame:(CGRect)frameafterSelectColor:(SelectColorBlock)afterSelectColor
afterSelectLineWidth:(SelectLineWidthBlock)afterSelectLineWidthselectEarser:(ToolViewActionBlock)selectEarserseletUndo:(ToolViewActionBlock)selectUndoselectClear:(ToolViewActionBlock)selectClearselectPhoto:(ToolViewActionBlock)selectPhoto
{self = [super initWithFrame:frame];if (self) {_selectColorBlock = afterSelectColor;_selectLineWidthBlock = afterSelectLineWidth;_selectEarserBlock = selectEarser;_selectUndoBlock = selectUndo;_selectClearBlock = selectClear;_selectPhotoBlock = selectPhoto;[self setBackgroundColor:[UIColor lightGrayColor]];// 通过循环的方式创建按钮NSArray *array = @[@"颜色", @"线宽", @"橡皮", @"撤销", @"清屏", @"相机", @"保存"];[self createButtonsWithArray:array];}return self;
}#pragma mark 创建工具视图中的按钮
- (void)createButtonsWithArray:(NSArray *)array
{// 按钮的宽度,起始点位置NSInteger count = array.count;CGFloat width = (self.bounds.size.width - (count + 1) * kButtonSpace)/ count;CGFloat height = self.bounds.size.height;NSInteger index = 0;for (NSString *text in array) {        MyButton *button = [MyButton buttonWithType:UIButtonTypeCustom];CGFloat startX = kButtonSpace + index * (width + kButtonSpace);[button setFrame:CGRectMake(startX, 8, width, height - 16)];[button setTitle:text forState:UIControlStateNormal];[button setTag:index];[button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];[self addSubview:button];// 测试代码
//        [button setSelectedMyButton:YES];index++;}
}#pragma mark 按钮监听方法
- (void)tapButton:(MyButton *)button
{// 方法1:遍历所有的按钮,将selectedMyButton设置为NO,取消所有的下方红线// 方法2:在属性中记录前一次选中的按钮,将该按钮的属性设置为NOif (self.selectButton != nil && self.selectButton != button) {[self.selectButton setSelectedMyButton:NO];}// 通过设置当前按钮selectedMyButton属性,在下方绘制红线[button setSelectedMyButton:YES];self.selectButton = button;switch (button.tag) {case kButtonColor:// 点击按钮的时候强行关闭当前显示的子视图[self forceHideView:self.colorView];// 显示/隐藏颜色选择视图[self showHideColorView];break;case kButtonLineWidth:// 点击按钮的时候强行关闭当前显示的子视图[self forceHideView:self.lineWidthView];// 显示/隐藏选择线宽视图[self showHideLineWidthView];break;case kButtonEarser:// 以变量的方式调用视图控制器的块代码_selectEarserBlock();[self forceHideView:nil];break;case kButtonUndo:_selectUndoBlock();[self forceHideView:nil];break;case kButtonClearScreen:_selectClearBlock();[self forceHideView:nil];break;case kButtonCamera:_selectPhotoBlock();[self forceHideView:nil];break;default:break;}
}#pragma mark - 子视图操作方法
#pragma mark 强行隐藏当前显示的子视图
// 如果显示的视图与传入的比较视图相同,就不再关闭
- (void)forceHideView:(UIView *)compareView
{// 1. 用属性记录当前显示的子视图,强行关闭该视图即可// 2. 遍历所有子视图,如果处于显示状态,则将其关闭// 3. 直接判断子视图,此方法仅适用于子数图数量极少UIView *view = nil;if (self.colorView.frame.origin.y > 0) {view = self.colorView;} else if (self.lineWidthView.frame.origin.y > 0) {view = self.lineWidthView;} else {return;}if (view == compareView) {return;}CGRect toFrame = view.frame;CGRect toolFrame = self.frame;toFrame.origin.y = -44;toolFrame.size.height = 44;[UIView animateWithDuration:0.5f animations:^{[self setFrame:toolFrame];[view setFrame:toFrame];}];
}#pragma mark 显示隐藏指定视图
- (void)showHideView:(UIView *)view
{// 2. 动画显示颜色视图CGRect toFrame = view.frame;// 工具条视图边框CGRect toolFrame = self.frame;if (toFrame.origin.y < 0) {// 隐藏的我们显示toFrame.origin.y = 44;toolFrame.size.height = 88;} else {toFrame.origin.y = -44;toolFrame.size.height = 44;}[UIView animateWithDuration:0.5f animations:^{[self setFrame:toolFrame];[view setFrame:toFrame];}];
}#pragma mark 显示隐藏选择线宽视图
- (void)showHideLineWidthView
{// 1. 懒加载选择线宽视图if (self.lineWidthView == nil) {SelectLineWidthView *view = [[SelectLineWidthView alloc]initWithFrame:CGRectMake(0, -44, 320, 44) afterSelectLineWidth:^(CGFloat lineWidth) {NSLog(@"%f", lineWidth);_selectLineWidthBlock(lineWidth);// 强行关闭线宽选择子视图[self forceHideView:nil];}];[self addSubview:view];self.lineWidthView = view;}[self showHideView:self.lineWidthView];
}#pragma mark 显示隐藏颜色视图
- (void)showHideColorView
{// 1. 懒加载颜色视图if (self.colorView == nil) {SelectColorView *view = [[SelectColorView alloc]initWithFrame:CGRectMake(0, -44, 320, 44) afterSelectColor:^(UIColor *color) {// 以函数的方式调用块代码变量_selectColorBlock(color);// 选中颜色后,强行关闭颜色选择子视图[self forceHideView:nil];NSLog(@"aaah");}];[self addSubview:view];self.colorView = view;}[self showHideView:self.colorView];
}@end
#import "MainViewController.h"
#import "DrawView.h"
#import "ToolView.h"@interface MainViewController ()@property (weak, nonatomic) DrawView *drawView;@end@implementation MainViewController#pragma mark - 实例化视图
- (void)loadView
{self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];;DrawView *drawView = [[DrawView alloc]initWithFrame:self.view.bounds];[self.view addSubview:drawView];self.drawView = drawView;ToolView *toolView = [[ToolView alloc]initWithFrame:CGRectMake(0, 0, 320, 44) afterSelectColor:^(UIColor *color) {// 给绘图视图设置颜色[drawView setDrawColor:color];} afterSelectLineWidth:^(CGFloat lineWidth) {// 工具视图选择线宽之后,需要执行的代码[drawView setLineWidth:lineWidth];} selectEarser:^{[drawView setDrawColor:[UIColor whiteColor]];[drawView setLineWidth:30.0];} seletUndo:^{[drawView undo];} selectClear:^{[drawView clearScreen];} selectPhoto:^{// 弹出图像选择窗口,来选择照片UIImagePickerController *picker = [[UIImagePickerController alloc]init];// 1. 设置照片源[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];// 2. 设置代理[picker setDelegate:self];// 3. 显示[self presentViewController:picker animated:YES completion:nil];}];[self.view addSubview:toolView];
}#pragma mark - 照片选择代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{UIImage *image = info[@"UIImagePickerControllerOriginalImage"];// 设置绘图视图[self.drawView setImage:image];// 关闭照片选择窗口[self dismissViewControllerAnimated:YES completion:nil];
}@end

转载于:https://my.oschina.net/khakiloveyty/blog/396543

iOS开发之Quartz 2D绘图相关推荐

  1. Quartz 2D绘图简介

    Quartz 2D绘图 简介 Quartz 2D是2D绘图引擎,适用iOS和Mac OS X程序.它提供底层轻量级的接口,并且会根据输出显示设备提供不匹配的逼真的画面  .Quartz 2D是与分辨率 ...

  2. iOS开发之AVKit框架使用

    2019独角兽企业重金招聘Python工程师标准>>> iOS开发之AVKit框架使用 一.引言 在iOS开发框架中,AVKit是一个非常上层,偏应用的框架,它是基于AVFounda ...

  3. (0045) iOS 开发之MBProgressHUD 源码学习

    (0045) iOS 开发之MBProgressHUD 源码学习 第一部分:学习所得和分析线程 1.  学习到了kvo 的使用 和屏幕方向的旋转判断. 2. 如果调起这个 HUD 的方法不是在主线程调 ...

  4. (0016)iOS 开发之Mac上Navicat Premium 创建远程连接和本地连接

    1.下载安装 (百度云盘里面有安装文件和注册机) 链接: https://pan.baidu.com/s/1kVG1k71 密码: mr5g 破解教程看这篇博客:http://blog.csdn.ne ...

  5. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

  6. Quartz 2d绘图

    今天看了一下Quartz 2D绘图,我只想说:不要把绘图和动画那些东西当做一个很复杂的东西,其实只要你认真看还是可以理解的.他们并不难.啰嗦了几句,现在直接进入正题: 前提是我们必须新建一个singl ...

  7. IOS开发之MD5加密和钥匙串的使用-oc

    IOS开发之MD5加密和钥匙串的使用-oc 源码在我的主页,md5加密是用户登录安全的一个保障.不可逆的,可以暴力破解的. // // ViewController.m // MD5演练 // // ...

  8. IOS开发之CALayer基本属性和使用

    IOS开发之CALayer基本属性和使用 // // ViewController.m // CALayer // // Created by 鲁军 on 2021/2/21. //#import & ...

  9. ios开发之plist 的文件的读写以及沙盒容器路径打印

    ios开发之plist 的文件的读写以及沙盒容器路径打印 核心代码在这里 // // ViewController.m // 21-plist存储和沙盒路径 // // Created by 鲁军 o ...

最新文章

  1. Zip文件中文乱码问题解决方法(MAC->Windows)
  2. spring事务模板使用
  3. 目前流行的装修风格_当下最流行十种装修风格,总有一款适合你!
  4. GitLab创建空仓库后拉取并上传文件遇到的系列问题
  5. C++中指针和引用的选择
  6. 音视频录制基础原理概念
  7. Java位运算符:Java移位运算符、复合位赋值运算符及位逻辑运算符
  8. 《C++沉思录》——类设计核查表、代理类、句柄类
  9. python画围棋棋盘_Python语言程序设计之二--用turtle库画围棋棋盘和正、余弦函数图形...
  10. Youtube更改视频原始语言
  11. userdel: user user is currently used by process 18752解决办法
  12. 史上最详细的 Win10系统重装教程(纯净版)
  13. 《电子元器件的可靠性》——第3章可靠性试验
  14. 编写LLVM Pass模块知识点梳理
  15. MEION:锁相环锁定状态仿真与板载测试情况分析
  16. 506 Relative Ranks 相对排名
  17. pytorch中tensor转numpy
  18. 优化方法理论合集(13)——可行域
  19. 中文核心期刊目录汇总(2020年12月发布)
  20. Qt之QGraphicsTextItem 去掉选中虚线框

热门文章

  1. ITK:VTK图像到ITK图像
  2. VTK:Filtering之ConstrainedDelaunay2D
  3. Qt Creator添加调试器
  4. OpenGL Compute Shader Image Processing计算着色器图像处理的实例
  5. 页面伪静态化 java_UrlRewrite 伪静态化页面
  6. 26.27.28.29.极区图(南丁格尔玫瑰图)、维恩图 (Venn diagram)、面状图(Area chart)、树地图
  7. 使用Docker虚拟化出一个Centos7操作系统(140、141机器上执行)
  8. dependencies与dependencyManagement的区(转自:http://blog.csdn.net/liutengteng130/article/details/46991829)
  9. Spark Streaming实现实时WordCount,DStream的使用,updateStateByKey(func)实现累计计算单词出现频率
  10. Hadoop中通过ToolRunner和Configured实现直接读取命令行动态出入reduce task数量,jar文件等