Core Graphics

Quartz 2D Programming Guide
Core Graphics (Framework)
Drawing(UIKit)、Images and PDF(UIKit)

1、Quartz 2D使用的是绘图者模式进行成像。也就是,页面上的绘制,会被后面的绘制操作叠加覆盖,比如如果先画一个五角星线条,后画一个圆形,则圆形会覆盖五角星的部分线条比如中间的五边形但如果圆形不够大则不会覆盖五角星的五个角。注意,已经绘制的无法修改,只能被后绘制的覆盖。
2、graphics context封装了绘图参数、与输出设备相关的特征信息(比如bitmap graphics context表示输出成bitmap,比如PDF graphics context表示输出成PDF)。
3、Quartz会根据current graphics state的参数修改绘图操作的结果,参数比如颜色、线宽等。
4、current transformation matrix(CTM)是对坐标系统进行映射,然后再在新的坐标系统中进行绘图,意思应该是指,原本的坐标是(x,y,z),通过乘以CTM矩阵变成(x’,y’,z’),然后在绘图坐标系中的(x’,y’,z’)位置绘制这个点。
5、Quartz使用名字带有“Create”、“Copy”的函数创建对象时,会拥有这个对象,所以必须在使用完成之后释放。名字不带有这两个关键字则不需要手动释放,这些对象会在某个时间点自动释放。
6、所有的绘制都要绘制到graphics context,比如线宽、颜色、变换等。UIView的drawRect:被调用之前已经创建好graphics context,使用UIGraphicsGetCurrentContext获取。(当view在屏幕上可见时或者它的内容需要更新时,drawRect被调用。)
7、Anti-Aliasing会让文字很模糊,颜色变浅,但是会让图形的边缘平滑,可以设置CGContextSetShouldAntialias来打开或关闭Anti-Aliasing,并且需要CGContextSetAllowsAntialiasing也为true时才会执行Anti-Aliasing。
8、如果想逆转 变换CTM所产生的效果,一般不用CGAffineTransformInvert,而是用graphics state的存储和恢复,也许是因为每一次设置参数时都已经保存在graphics state中,存储和恢复只需要执行push和pop操作让state入栈出栈,而invert需要复杂的数学计算。
9、好像如果CGContextSetXX修改了graphics state(比如CGContextSetShadow),则接下来的绘制都使用所设置的状态,除非再次修改CGContextSetXX才会使接下来的绘制使用再次修改后的状态。
10、好像generic RGB color spaces在iOS无效,应该用DeviceRGB。
11、Quartz 2D Programming Guide有很多代码示例。
12、一直以为bitmap是指PNG,原来JPEG、TIFF、PNG都是bitmap image。
13、在某些情况下,生成副本的拷贝操作遵循“copy-on-write”语义,也就是只有当原始数据被修改时才会进行真正的物理拷贝,如果副本被销毁之前都没有修改原始数据,则副本和原始数据其实是同一块内存。
14、Core Graphics (Framework) 的CGContext有很多画图绘制接口和其他常用接口,CGPath有创建形状线条接口,然后绘制要用CGContext的接口。
15、是创建一个CGAffineTransform,还是直接使用CGContextScaleCTM,取决于这个transform要不要复用,如果复用则需要创建CGAffineTransform再concat到CTM,而不是直接修改CTM。同样,是创建一个CGPath还是直接使用CGContext的接口,取决于这个path是否需要复用。
16、一个bitmap image mask是决定一个颜色如何被传输(transfer),而不是决定使用哪种颜色。image mask中的每个样本值都指定当前填充颜色在特定位置被遮盖的量。
17、DrawingImages and PDF包含UIGraphicsxx相关函数。
18、CGPath
(1)调用完CGContextAddPath(ctx, path0);CGContextStrokePath(ctx);之后路径就清空了,所以接着调用CGContextFillPath(ctx);并不会填充路径,所以如果想要既描边又填充,需要在调用xxFillxx之前再调用一次添加路径,即CGContextAddPath(ctx, path0);CGContextFillPath(ctx);
(2)CGPathCreateCopyByDashingPath产生的dash_path,如果用CGContextFillPath绘制是无效的,既不会填充虚线本身,也不会填充虚线构成的形状(官方文档中Discussion的说明是什么意思呢?);用CGContextStrokePath绘制是有效,而如果还设置了CGContextSetLineDash,则这个设置的效果会叠加在dash_path之上而不是替换,也就是原本的dash_path的unpainted部分仍然不绘制,而原本的dash_path的painted部分如果处于CGContextSetLineDash所设置的unpainted部分则不绘制。
(3)CGPathCreateCopyByStrokingPath产生的新路径,如果用CGContextFillPath绘制,则效果等同于对原始路径使用CGContextStrokePath绘制;如果用CGContextStrokePath绘制,则发现会有两组平行的线段构成填充图形,而且内层的路径在拐角处会有交叉三角形,而且可以调用CGContextSetLineJoin、CGContextSetLineCap、CGContextSetLineDas对这些线段进行样式设置。总之就是,CGPathCreateCopyByStrokingPath会自动生成两个subpath组成一个填充区域为原本线段的stroke区域。
代码示例:(先描边再填充就可以遮盖拐角处的三角形。)

 CGContextSetLineWidth(ctx, 5);CGMutablePathRef path = CGPathCreateMutable();CGPathMoveToPoint(path, NULL, 10, 10);CGPathAddLineToPoint(path, NULL, 200, 50);CGPathAddLineToPoint(path, NULL, 100, 200);CGPathCloseSubpath(path);CGPathRef path0 = CGPathCreateCopyByStrokingPath(path, NULL, 20, kCGLineCapSquare, kCGLineJoinBevel, 10); // 最后一个参数miterLimit在kCGLineJoinMiter时设置为0-2才能看出这个参数的效果// 右一// CGPathRef path0 = CGPathCreateCopyByStrokingPath(path, NULL, 20, kCGLineCapSquare, kCGLineJoinRound, 10);// 左一CGContextAddPath(ctx, path0);CGContextDrawPath(ctx, kCGPathFillStroke);// 左二CGContextAddPath(ctx, path0);CGContextStrokePath(ctx);CGContextAddPath(ctx, path0);CGContextFillPath(ctx);// 右二CGContextSetLineJoin(ctx, kCGLineJoinRound);CGContextSetLineCap(ctx, kCGLineCapRound);CGFloat dash1[2] = {10, 10};CGContextSetLineDash(ctx, 0, dash1, 2);CGContextAddPath(ctx, path0);CGContextFillPath(ctx);CGContextAddPath(ctx, path0);CGContextStrokePath(ctx);


19、CGContextReplacePathWithStrokedPath:效果和CGPathCreateCopyByStrokingPath类似,只不过CGPathCreateCopyByStrokingPath所需要传入参数如lineWidth、lineCap、lineJoin、miterLimit这些,会直接使用CGContextSetLineWidth、CGContextSetLineJoin这些函数所设置的值,所以在调用CGContextReplacePathWithStrokedPath之前要设置线宽足够大,然后在调用CGContextStrokePath绘制之前,重新调用CGContextSetLineWidth设置线宽比之前小,不然看不出CGContextReplacePathWithStrokedPath的效果。
下图左边:

 CGContextAddPath(ctx, path0);CGContextSetLineWidth(ctx, 10);CGContextReplacePathWithStrokedPath(ctx);CGContextSetLineWidth(ctx, 1);CGPathRef tempPath = CGContextCopyPath(ctx);CGContextFillPath(ctx);CGContextAddPath(ctx, tempPath);CGContextStrokePath(ctx);


20、CGContextClip:裁切边缘不会自动加上描边;先裁切后绘制,才会看出裁切效果。
上图右边:

 CGMutablePathRef pathc = CGPathCreateMutable();CGPathMoveToPoint(pathc, NULL, 0, 0);CGPathAddLineToPoint(pathc, NULL, 220, 0);CGPathAddLineToPoint(pathc, NULL, 0, 100);CGPathCloseSubpath(pathc);CGContextAddPath(ctx, pathc);CGContextClip(ctx);CGContextAddPath(ctx, path0);CGContextDrawPath(ctx, kCGPathFillStroke);

View Controller

Creating a Custom Container View Controller
UIViewController
View Controller Programming Guide for iOS

1、在将子视图控制器的视图添加到父视图控制器(即容器视图控制器)的视图上之前,必须先将这个子视图控制器和父视图控制器关联起来,也就是调用“addChildViewController:”,这是为了让iOS可以正确地将事件路由到子视图控制器和它管理的视图。
2、容器视图控制器使得可以通过更易于管理和可复用的方式组装精细的界面。
3、容器视图控制器可以设置子视图控制器的视图cview的大小和位置(因为cview会通过addSubview嵌套到容器视图控制器的视图中),而cview的子视图的大小位置内容是由子视图控制器管理(也就是创建和修改cview的子视图的代码在子视图控制器中)。比如UINavigationController是容器视图控制器,它的根视图控制器rvc和已经push的视图控制器puvc都是它的子视图控制器(UINavigationController是这些子视图控制器的父视图控制器),rvc.view的subviews的创建修改代码在rvc中。
4、添加一个子视图控制器的步骤:
(1)调用父视图控制器的addChildViewController:添加子视图控制器;(这个方法会自动调用子视图控制器的willMoveToParentViewController:。)
(2)调用父视图控制器的pview的addSubview:添加子视图控制器的cview;(不要修改cview和它的子视图的内容。)
(3)设置cview的位置和大小即frame,或者设置约束;
(4)调用子视图控制器的didMoveToParentViewController:!!(这一步是为了给子视图控制器提供机会对视图所有权的变化做出反应。)
(移除步骤:参看官方文档)
5、不要将一个视图控制器的view嵌入其他视图中,除非这两个视图控制器是容器与子视图控制器的关系,否则会出现一些问题比如状态保存恢复系统会无法正确地找到所需的视图控制器。
6、“[vc presentViewController:vc2 animated:NO completion:nil];”,vc和vc2不是容器与子视图控制器的关系(即vc.childViewControllers不包含vc2,vc2.parentViewController不是vc),vc.presentedViewController = vc2,vc2.presentingViewController = vc。

UICollectionView

UICollectionView
Layouts
UICollectionViewController

1、UICollectionView可以使用自己定制的各种布局显示数据项。(而UITableView显示数据项只能从上到下一行一行地显示。)
2、“Layouts->Customizing Collection View Layouts”包含示例代码。
3、一个layout对象决定cell、supplementary view、decoration view的放置。

UICollectionView的Layout

1、UICollectionReusableView的- preferredLayoutAttributesFittingAttributes::如果是UICollectionViewFlowLayout,则每一次cell即将出现时都调用这个方法,且修改frame.size生效,修改frame.origin不生效;如果是自定义的UICollectionViewLayout子类,且重写的- layoutAttributesForElementsInRect:方法实现中返回空数组时,则不会调用,如果返回的不是空数组且对应cell有attributes则该cell即将出现时会调用这个方法,总之不需要在方法实现中手动调用cell的这个方法(在UICollectionViewLayout的“- prepareLayout”和“- layoutAttributesForElementsInRect:”方法调用时cell为nil)(自定义的UICollectionViewLayout子类要使cell的“- preferredLayoutAttributesFittingAttributes:”返回的attribute生效(比如修改了frame.origin和size),需要重写- shouldInvalidateLayoutForPreferredLayoutAttributes:withOriginalAttributes:返回YES)。
2、自定义的UICollectionViewLayout子类重写- layoutAttributesForElementsInRect:,这个方法会在cell布局时调用,而- layoutAttributesForItemAtIndexPath:需要手动调用UICollectionView的“- layoutAttributesForItemAtIndexPath:”才会调用。
3、UICollectionView滑动时,会调用UICollectionViewLayout的- shouldInvalidateLayoutForBoundsChange:,size不变只有origin变化比如y,如果这个方法返回YES,则会调用- prepareLayout重新计算布局。
4、“- layoutAttributesForElementsInRect:”被调用时的size大多数情况是(collectionView宽度,屏幕高度),除了有时上拉加载出现两倍屏幕高度,往下滚动到collectionView最顶部时y可能会变成“-屏幕高度”;当内容已经布局好,且“- shouldInvalidateLayoutForBoundsChange:”在newBounds.size和当前size相等时返回YES,则上下滚动时不会再调用这个方法。

UICollectionViewCell

1、UICollectionViewCell子类要重写“- initWithFrame:”初始化方法,而不是“- init”。

UITableView

UITableView

1、UITableViewDragDelegate:使用的时候先设置UITableView的dragInteractionEnabled=YES和dragDelegate,然后实现协议如下,不能返回空数组,否则看不到拖动效果,长按cell一段时间然后拖动,会发现cell浮起来随手指移动且原本位置的视图变暗。(以下示例只是展示Drag的效果,真正使用时要考虑UITableViewDragDelegate其他协议方法的作用以及UIDragItem如何创建。)

- (NSArray<UIDragItem *> *)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath {return @[[[UIDragItem alloc] initWithItemProvider:[NSItemProvider new]]];
}

第三方库链接

Masonry

Masonry

1、用法参看GitHub->README.md的示例。

AFNetworking

AFNetworking

1、用法参看GitHub->README.md的示例、源文件.h的注释说明,比如“AFHTTPSessionManager.h”文件开头的注释“ ## Subclassing Notes”、“## Serialization”。
2、AFHTTPSessionManager的“+ manager”不是单例,AFHTTPSessionManager的requestSerializer默认是一个AFHTTPRequestSerializer实例,responseSerializer默认是AFJSONResponseSerializer。
3、
(1)AFHTTPRequestSerializer,表示会将- POST:parameters:headers:progress:success:failure:等AFHTTPSessionManager网络请求方法中传入的parameters字典转成“k1=v1&k2=v2&…”格式,然后设置为HTTPBody(消息体),如果用Charles抓包则这部分数据显示在Contents->Form中。
(2)AFJSONRequestSerializer,表示会将- POST:parameters:headers:progress:success:failure:等方法中传入的parameters字典转成“{“k1”:“v1”,“k2”:“v2”,…}”格式(JSON格式),然后设置为HTTPBody(消息体),如果用Charles抓包则这部分数据显示在Contents->JSON Text中。
(3)由于AFHTTPSessionManager默认的requestSerializer是AFHTTPRequestSerializer类型,如果要求请求消息体是JSON字符串类型,则需要将AFHTTPSessionManager实例的requestSerializer设置为AFJSONRequestSerializer实例,如sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
4、“- POST:parameters:headers:progress:success:failure:”中的headers字典会自动转换成[request setValue:@"v1" forHTTPHeaderField:@"k1"];

ReactiveObjC

ReactiveObjC

1、原本是Objective-C ReactiveCocoa,现在的名字是ReactiveObjC,具体介绍参看GitHub->README.md和里面的链接,README.md、Documentation/BasicOperators.md、Documentation/DesignGuidelines.md中有使用示例。
2、在Podfile添加pod 'ReactiveObjC', '~> x.x.x'导入ReactiveObjC,“pod search ReactiveObjC”搜索版本。

MJRefresh

MJRefresh

1、编译之后的.app文件中包含MJRefresh.bundle(里面包含图片资源)。

MBProgressHUD

jdg/MBProgressHUD
matej/MBProgressHUD(pod search显示的Source地址,MBProgressHUD.h.m的创建者)

1、比起同类型的SVProgressHUD,编译之后不包含SVProgressHUD.bundle文件,而且支持定制。
2、graceTime、minShowTime等属性按需设置。
3、MBProgressHUD的位置可以随着视图高度变化仍然保持居中,但如果父视图是UICollectionView则cv的高度变大时hud没有保持居中而是偏上,原因是cv.bounds.origin.y不是0,所以最好不要将hud添加到UICollectionView或UITableView(README.mdown->Usage有说明)。如果要随着UICollectionView高度变化保持居中,可以添加到一个和UICollectionView相同位置的透明视图上。

官方文档链接(Core Graphics、View Controller、UICollectionView、UITableView、第三方库)相关推荐

  1. 如何在ORACLE CLOUD中创建和访问容器集群丨内附官方文档链接

    墨墨导读:本文描述如何在Oracle Cloud中创建并访问容器服务.为了简单,所有的操作都是针对root隔离区. 创建允许容器运行的政策官方文档链接 这一步是必须的,否则可以增加容器容器. 官方文档 ...

  2. Visual Studio中C++部分的官方文档链接【微软(Microsoft)所有产品的官方文档链接】

    目前(2022年07月),微软官方网站上关于Visual Studio的文档,最老的版本也是VS2015了,如下图所示: 微软所有产品的文档目录: 中文版:https://docs.microsoft ...

  3. 【pytest官方文档】解读- 开发可pip安装的第三方插件

    在上一篇的 hooks 函数分享中,开发了一个本地插件示例,其实已经算是在编写插件了.今天继续跟着官方文档学习更多知识点. 一个插件包含一个或多个钩子函数,pytest 正是通过调用各种钩子组成的插件 ...

  4. SQL Server中UPDATE和DELETE 微软MSDN官方文档链接

    UPDATE (Transact-SQL) DELETE (Transact-SQL)

  5. Spring 4 官方文档学习 Spring与Java EE技术的集成

    本部分覆盖了以下内容: Chapter 28, Remoting and web services using Spring -- 使用Spring进行远程和web服务 Chapter 29, Ent ...

  6. [译] AsyncDisplayKit/Texture 官方文档(1)

    官方文档链接:texturegroup.org/docs/gettin- 开始使用 Texture Texture 的基本单位是 Node,ASDisplayNode 是 UIView 和 CALay ...

  7. RabbitMQ官方文档知识点总结合集+代码注释(中文+Java版)

    全文代码.MD格式文档的github连接(求star~):https://github.com/Ruoyi-Chen/RabbitMQ-demos 文章目录 全文代码.MD格式文档的github连接( ...

  8. ceph常用命令及其使用、ceph集群定位常用命令说明【如ceph osd set norebalance】、ceph官方文档查询地址

    文章目录 ceph集群的监控 查看OSD版本 检查集群的健康情况 监控集群的时间 查看集群的空间利用率 查看集群的状态 查看集群的实时状态 获取秘钥列表 查看ceph特征 查看osd存储引擎 获得所有 ...

  9. ASP.NET Core Razor官方文档踩坑

    环境:ASP.NET Core 3.1 工具:VS2019 官方文档的起始页地址:教程:使用 ASP.NET Core 创建 Razor Pages Wb 应用 | Microsoft Learn 添 ...

最新文章

  1. android 悬浮窗权限,Android 悬浮窗权限校验
  2. 跨平台日志清理工具 Log-Cutter v1.0.3 正式发布
  3. 用手机写代码:基于 Serverless 的在线编程能力探索
  4. java mvc下载文件_Springmvc实现文件下载2种实现方法
  5. 【数据结构和算法笔记】队列(Queue)详解:c实现
  6. 分享Silverlight/WPF/Windows Phone一周学习导读(4月18日-4月23日)
  7. Visual Studio问题汇总
  8. 安装docker的可视化UI——Portainer
  9. 【已修复】U盘做系统盘后内存变小
  10. c语言法定节日日历程序,C 语言写的日历
  11. SS-Model【3】:DeepLabv2
  12. 怎么恢复计算机误删的用户组,如何恢复误删的用户组
  13. 机器学习 - 随机森林 Random Forest
  14. 在C或C++中如何使用PI(π)值
  15. 歌礼扩大利托那韦口服片剂产能;博奥信生物任命叶信良博士为首席战略官兼中国区商务拓展负责人 | 医药健闻...
  16. 关系型数据库选型MySQL、 Oracle、SQL server、DB2、PostgreSql
  17. windows修改ntp服务器端口,windows ntp 服务器 端口号
  18. 乐见Safengine licensor终于有了脱壳脚本
  19. 今日进度--论文5.10
  20. 华为云服务器,新用户福利!!0元免费体验云产品最长可达一年

热门文章

  1. iframe的allowTransparency属性
  2. YOLO 超详细入门(含开源代码)——网络结构、细节、目标损失函数、优点
  3. 阿里大鱼 php 短信接口,dedecms使用阿里大鱼短信接口进行短信发送
  4. DOS 直接从C盘跳到D盘子目录
  5. 【实验学习】思科模拟器学习
  6. Flutter NavigationBar 优雅的实现底部导航栏菜单
  7. 2021年制冷与空调设备运行操作考试APP及制冷与空调设备运行操作找解析
  8. qq个人中心模块测试用例和一套数据库题
  9. 竞选]美国总统竞选 奥巴马 演讲
  10. 十六进制表示法(进制转换)