Quartz2D绘制曲线

使用函数绘制曲线

Quartz 2D提供了CGContextAddCurveToPoint() 函数和CGContextAddQuadCurveToPoint()两个函数来向当前上下文添加曲线,前者用于添加贝塞尔曲线,后者用于添加二次曲线。
确定一条贝塞尔曲线需要4个点:开始点、第一个控制点、第二个控制点和结束点。

确定一条二次曲线需要三个点:开始点、控制点和结束点。

添加贝塞尔曲线

CGContextAddCurveToPoint()

CGContextRef ctx = UIGraphicsGetCurrentContext();

// 添加曲线路径
// 设置起点
CGContextMoveToPoint(ctx, 0, 0);
  • 参数1: 上下文对象
  • 参数2: 控制点1X坐标
  • 参数3: 控制点1Y坐标
  • 参数4: 控制点2X坐标
  • 参数5: 控制点2Y坐标
  • 参数6: 终点x坐标
  • 参数7: 终点Y坐标

code:

CGContextAddCurveToPoint(ctx, 30, 200, 300, 20, 300, 300);

// 设置颜色
[[UIColor magentaColor] setStroke];

// 渲染
CGContextStrokePath(ctx);

// 关闭图形上下文
CGContextClosePath(ctx);
添加二次曲线
CGContextAddQuadCurveToPoint()

// 获取图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// 起始点
CGContextMoveToPoint(ctx, 20, 10);
  • 参数: 图形上下文
  • 参数: 控制点坐标
  • 参数: 结束点坐标

添加二次曲线

CGContextAddQuadCurveToPoint(ctx, 30, 200, 200, 40);

[[UIColor cyanColor] setStroke];
CGContextStrokePath(ctx);
// 关闭图形上下文
CGContextClosePath(ctx);

绘制形状

使用绘制二次曲线的函数绘制花瓣

程序中CGContextAddFlower代码分别添加5瓣花朵路径、6瓣花朵路径、7瓣花朵路径,然后使用不同的颜色来填充这些路径。注意到上面的程序并未在每次添加花朵路径后立即关闭,这也是允许的,而且每次填充路径时并不会再次填充前一次已经填充过的路径。这是因为只用程序绘制了CGContextRef当前所包含的路径,系统会自动清除已经绘制的路径。

注意:每次绘制完成后,CGContextRef会自动清除已经绘制完成的路径

该方法负责绘制花朵。
n:该参数控制花朵的花瓣数;dx、dy:控制花朵的位置;size:控制花朵的大小;
length:控制花瓣的长度

void CGContextAddFlower(CGContextRef c , NSInteger n
                        , CGFloat dx , CGFloat dy , CGFloat size , CGFloat length)
{
    CGContextMoveToPoint(c , dx , dy + size);  // 移动到指定点
    CGFloat dig = 2 * M_PI / n;
    // 采用循环添加n段二次曲线路径
    for(int i = 1; i < n + 1 ; i++)
    {
        // 计算控制点坐标
        CGFloat ctrlX = sin((i - 0.5) * dig) * length + dx;
        CGFloat ctrlY= cos((i - 0.5 ) * dig) * length + dy;
        // 计算结束点的坐标
        CGFloat x = sin(i * dig) * size + dx;
        CGFloat y =cos(i * dig) * size + dy;
        // 添加二次曲线路径
        CGContextAddQuadCurveToPoint(c, ctrlX , ctrlY , x , y);
    }
}

绘制花瓣

- (void)drawStar
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();  // 获取绘图的CGContextRef
    CGContextBeginPath(ctx);  // 开始添加路径
    CGContextAddFlower(ctx , 5 , 50 , 100 , 30 , 80);  // 添加5瓣花朵的路径
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);  // 设置填充颜色
    CGContextFillPath(ctx);
    CGContextAddFlower(ctx , 6 , 160 , 100 , 30 , 80);  // 添加6瓣花朵的路径
    CGContextSetRGBFillColor(ctx, 1, 1, 0, 1);  // 设置填充颜色
    CGContextFillPath(ctx);
    CGContextAddFlower(ctx , 7 , 270 , 100 , 30 , 80);  // 添加7瓣花朵的路径
    CGContextSetRGBFillColor(ctx, 1, 0, 1, 1);  // 设置填充颜色
    CGContextFillPath(ctx);
    CGContextClosePath(ctx);  // 关闭路径
}

Quartz2D 初识

Quartz2D 二维绘图引擎,支持iOS和Mac系统么,可以实现的功能有

  • 绘制图形: 线条,三角形,矩形,圆,弧等
  • 绘制文字
  • 绘制图像或者图片
  • 读取生成PDF
  • 截图/裁剪图片
  • 自定义UI控件
  • 手势解锁
  • 图形上下文

保存绘图信息和状态

确定输出目标(PDF,Bitmap或者显示器)

Bitmap Graphics Context
PDF Granhics Context
Window Graphics Context
Layer Graphics Context

绘制线段

- (void)drawLine {
    // 获取图形上下文
    // 所用的是UIGraphics上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 创建描述路径
    CGMutablePathRef path = CGPathCreateMutable();
    // 设置起点
    // path : 表示给那个路径设置起点
    CGPathMoveToPoint(path, NULL, 10, 10);
    CGPathAddLineToPoint(path, NULL, 80, 80);

    // 添加路径到上下文
    CGContextAddPath(ctx, path);

    // 渲染
    CGContextStrokePath(ctx);
}

系统底层自动将路径添加到图形上下文

- (void)drawLine2 {

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 描述路径
    // 此方法底层会自动将路径添加到图形上下文
    CGContextMoveToPoint(ctx, 50, 50);
    CGContextAddLineToPoint(ctx, 100, 100);

    CGContextSetLineWidth(ctx, 5);

    [[UIColor redColor] set];
    // 渲染
    CGContextStrokePath(ctx);
}

使用C语言函数的封装

- (void)drawLine3 {
    // 使用UIKit 已经封装的功能,面向对象
    // 贝塞尔路径

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(10, 10)];
    [path addLineToPoint:CGPointMake(50, 50)];

    // 绘制路径
    [path stroke];
}

绘制多条线段

  • 绘制多条线,状态不好管理
  • 默认下一条线的起点是上一条线的终点
  • 绘制多天不连接的线时需要重新设置起点
  • 为了方便管理,应该让每一条线对应一条路径
  • 使用UIBeizerPath

code:

- (void)drawMoreLine {
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 描述路径
    CGContextMoveToPoint(ctx, 20, 20);
    CGContextAddLineToPoint(ctx, 100, 100);

    // 设置第二条线的起点
    CGContextMoveToPoint(ctx, 20, 30);
    CGContextAddLineToPoint(ctx, 150, 100);

    // 设置绘图状态要在渲染之前,都是给上下文设置
    // 描边颜色
    [[UIColor greenColor] setStroke];
    // 线宽
    CGContextSetLineWidth(ctx, 10);
    // 连接样式
    // kCGLineJoinMiter,    斜接
    // kCGLineJoinRound,    圆角
    // kCGLineJoinBevel     平切
    CGContextSetLineJoin(ctx, kCGLineJoinBevel);
    // 顶角样式,线的顶端效果
    CGContextSetLineCap(ctx, kCGLineCapRound);

    // 渲染
    CGContextStrokePath(ctx);
}

使用UIBezierPath 绘制多条直线并设置不同状态

- (void)drawUIBezierPahtState {

    // 第一条线
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(10, 10)];
    [path addLineToPoint:CGPointMake(80, 80)];

    path.lineWidth = 20;
    path.lineJoinStyle = kCGLineJoinRound;
    path.lineCapStyle = kCGLineCapRound;
    [[UIColor redColor] setStroke];

    [path stroke];

    // 第二条线
    {
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(40, 70)];
        [path addLineToPoint:CGPointMake(150, 40)];

        path.lineWidth = 20;
        path.lineJoinStyle = kCGLineJoinRound;
        path.lineCapStyle = kCGLineCapRound;
        [[UIColor greenColor] setStroke];

        [path stroke];
    }
}

OC中运行时

RunTime
对于C语言,函数的调用在编译的时候会决定调用哪个函数,而对于面向对象的语言对于[调用某个对象的方法或函数]就叫「消息传递」。所以在 Java,C++ 这些语言里[调用某个对象的方法或函数]和 Objective-C 里[向某个对象发送消息]在概念上就是一样的事情,

RunTime 简介

  • RunTime 简称运行时,OC中通常叫运行时机制,主要的是消息机制
  • 消息机制:在OC中,属于动态调用,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用

RunTime 作用

  • 发送消息:让对象发送消息
  • 交换方法
  • 动态添加方法
  • 动态获取属性和方法
  • 字典转模型
  • 给分类添加属性

原理:给分类添加一个属性,重写了setter、getter方法,但是没有生成 _成员变量,需要通过运行时关联到分类中, 其本质上就是给这个类添加关联,存值和取值
code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
self.oldurlPath = urlPath;

- (void)setOldurlPath:(NSString *)oldurlPath {

// RunTime 关联
// 第一个参数:给哪个对象添加关联
// 第二个参数:关联的key,通过这个key获取
// 第三个参数:关联的value
// 第四个参数:关联的策略
objc_setAssociatedObject(self, key, oldurlPath, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)oldurlPath {
return objc_getAssociatedObject(self, key);
}

WKWebiView 使用

WKWebiView iOS8.0 出现,性能要远远好于 iOS 2.0时出现的 UIWebView,主要记录WKWebView 的创建和代理方法

创建WKWebView

WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
self.webView = webView;
[self.view addSubview:webView];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];

遵守协议 WKNavgationDelegate WKUIDelegate

代理方法

  • WKNavgationDelegate 方法

    • 发送请求之前决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

      decisionHandler(WKNavigationActionPolicyAllow);
      // 不允许跳转
      decisionHandler(WKNavigationActionPolicyCancel);
      NSLog(@"decidePolicyForNavigationAction");
      }
    • 收到相应之后决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      8
      9
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

      decisionHandler(WKNavigationResponsePolicyAllow);

      decisionHandler(WKNavigationResponsePolicyCancel);

      NSLog(@"decidePolicyForNavigationResponse");

      }
    • 开始加载时调用

      1
      2
      3
      4
      - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {

      NSLog(@"didStartProvisionalNavigation");
      }
    • 接受到服务器的跳转请求时调用

      1
      2
      3
      - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
      NSLog(@"didReceiveServerRedirectForProvisionalNavigation");
      }
- 页面加载失败时调用 **存在缓存问题**

1
2
3
4
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

NSLog(@"error= %@", error);
}
- 内容开始返回时调用
1
2
3
4
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {

NSLog(@"didCommitNavigation");
}
  • 内容返回成功后调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {

    NSLog(@"didFinishNavigation");
    }
  • 开始返回错误时调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

    NSLog(@"didFailNavigation");
    }
  • 目前不知道什么时候调用

    1
    2
    3
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"didReceiveAuthenticationChallenge");
    }
    • 目前不知道什么时候调用

      1
      2
      3
      4
      - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)) {

      NSLog(@"webViewWebContentProcessDidTerminate");
      }

WKWebiView 使用

WKWebiView iOS8.0 出现,性能要远远好于 iOS 2.0时出现的 UIWebView,主要记录WKWebView 的创建和代理方法

创建WKWebView

WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
self.webView = webView;
[self.view addSubview:webView];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];

遵守协议 WKNavgationDelegate WKUIDelegate

代理方法

  • WKNavgationDelegate 方法

    • 发送请求之前决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

      decisionHandler(WKNavigationActionPolicyAllow);
      // 不允许跳转
      decisionHandler(WKNavigationActionPolicyCancel);
      NSLog(@"decidePolicyForNavigationAction");
      }
    • 收到相应之后决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      8
      9
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

      decisionHandler(WKNavigationResponsePolicyAllow);

      decisionHandler(WKNavigationResponsePolicyCancel);

      NSLog(@"decidePolicyForNavigationResponse");

      }
    • 开始加载时调用

      1
      2
      3
      4
      - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {

      NSLog(@"didStartProvisionalNavigation");
      }
    • 接受到服务器的跳转请求时调用

      1
      2
      3
      - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
      NSLog(@"didReceiveServerRedirectForProvisionalNavigation");
      }
- 页面加载失败时调用 **存在缓存问题**

1
2
3
4
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

NSLog(@"error= %@", error);
}
- 内容开始返回时调用
1
2
3
4
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {

NSLog(@"didCommitNavigation");
}
  • 内容返回成功后调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {

    NSLog(@"didFinishNavigation");
    }
  • 开始返回错误时调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

    NSLog(@"didFailNavigation");
    }
  • 目前不知道什么时候调用

    1
    2
    3
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"didReceiveAuthenticationChallenge");
    }
    • 目前不知道什么时候调用

      1
      2
      3
      4
      - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)) {

      NSLog(@"webViewWebContentProcessDidTerminate");
      }

WKWebiView 使用

WKWebiView iOS8.0 出现,性能要远远好于 iOS 2.0时出现的 UIWebView,主要记录WKWebView 的创建和代理方法

创建WKWebView

WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
self.webView = webView;
[self.view addSubview:webView];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];

遵守协议 WKNavgationDelegate WKUIDelegate

代理方法

  • WKNavgationDelegate 方法

    • 发送请求之前决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

      decisionHandler(WKNavigationActionPolicyAllow);
      // 不允许跳转
      decisionHandler(WKNavigationActionPolicyCancel);
      NSLog(@"decidePolicyForNavigationAction");
      }
    • 收到相应之后决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      8
      9
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

      decisionHandler(WKNavigationResponsePolicyAllow);

      decisionHandler(WKNavigationResponsePolicyCancel);

      NSLog(@"decidePolicyForNavigationResponse");

      }
    • 开始加载时调用

      1
      2
      3
      4
      - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {

      NSLog(@"didStartProvisionalNavigation");
      }
    • 接受到服务器的跳转请求时调用

      1
      2
      3
      - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
      NSLog(@"didReceiveServerRedirectForProvisionalNavigation");
      }
- 页面加载失败时调用 **存在缓存问题**

1
2
3
4
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

NSLog(@"error= %@", error);
}
- 内容开始返回时调用
1
2
3
4
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {

NSLog(@"didCommitNavigation");
}
  • 内容返回成功后调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {

    NSLog(@"didFinishNavigation");
    }
  • 开始返回错误时调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

    NSLog(@"didFailNavigation");
    }
  • 目前不知道什么时候调用

    1
    2
    3
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"didReceiveAuthenticationChallenge");
    }
    • 目前不知道什么时候调用

      1
      2
      3
      4
      - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)) {

      NSLog(@"webViewWebContentProcessDidTerminate");
      }

WKWebiView 使用

WKWebiView iOS8.0 出现,性能要远远好于 iOS 2.0时出现的 UIWebView,主要记录WKWebView 的创建和代理方法

创建WKWebView

WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
self.webView = webView;
[self.view addSubview:webView];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];

遵守协议 WKNavgationDelegate WKUIDelegate

代理方法

  • WKNavgationDelegate 方法

    • 发送请求之前决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

      decisionHandler(WKNavigationActionPolicyAllow);
      // 不允许跳转
      decisionHandler(WKNavigationActionPolicyCancel);
      NSLog(@"decidePolicyForNavigationAction");
      }
    • 收到相应之后决定是否跳转

      1
      2
      3
      4
      5
      6
      7
      8
      9
      - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

      decisionHandler(WKNavigationResponsePolicyAllow);

      decisionHandler(WKNavigationResponsePolicyCancel);

      NSLog(@"decidePolicyForNavigationResponse");

      }
    • 开始加载时调用

      1
      2
      3
      4
      - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {

      NSLog(@"didStartProvisionalNavigation");
      }
    • 接受到服务器的跳转请求时调用

      1
      2
      3
      - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
      NSLog(@"didReceiveServerRedirectForProvisionalNavigation");
      }
- 页面加载失败时调用 **存在缓存问题**

1
2
3
4
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

NSLog(@"error= %@", error);
}
- 内容开始返回时调用
1
2
3
4
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {

NSLog(@"didCommitNavigation");
}
  • 内容返回成功后调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {

    NSLog(@"didFinishNavigation");
    }
  • 开始返回错误时调用

    1
    2
    3
    4
    - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

    NSLog(@"didFailNavigation");
    }
  • 目前不知道什么时候调用

    1
    2
    3
    - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"didReceiveAuthenticationChallenge");
    }
    • 目前不知道什么时候调用

      1
      2
      3
      4
      - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)) {

      NSLog(@"webViewWebContentProcessDidTerminate");
      }

git 使用

使用 git 提交代码

  • 初始化工作目录

    1
    git init
  • 配置用户名和邮箱(当前仓库)

    1
    2
    git config user.name "aTreey"
    git config user.email "480814177@qq.com"
  • 配置全局的用户名和密码

    1
    2
    git config --global user.name "aTreey"
    git config --global user.email "480814177@qq.com"
  • 创建文件

    1
    touch main.m
  • 添加文件到暂缓区

    1
    git add main.m
  • 查看文件状态

    1
    git status
  • 新添加的文件或者新修改的文件在工作区中,没有添加到暂缓区中

1
Untracked files: (红色)
  • 需要添加到暂缓区中
1
git add main.m
  • 出现一下提示方可提交
1
Changes to be committed: (绿色)
  • 给git起别名

    1
    2
    git config alias.st "status"
    git config alias.ci "commit -m"
  • 查看所有版本库日志(只能查看当前版本的以前日志)

    1
    git log
  • 查看指定文件的版本库日志

    1
    git log 文件名
  • 查看所有的操作的日志

    1
    git reflog

版本会退

  • 强制回退到当前版本

    1
    git reset --hard HEAD
  • 强制回退到当前版本的上一个版本

    1
    git reset --hard HEAD^
  • 强制回退到当前版本的上上个版本

    1
    git reset --hard HEAD^^
  • 强制回退到当前版本的前100个版本

    1
    git reset --hard HEAD~100
  • 强制回退指定版本

    1
    git reset --hard HEAD 版本号前七位

TableView 使用

tableView 使用总结

  • 字典的 key enumerator 的使用

  • tableViewCell 的 selected 方法可以监听cell 的选中, 使用selected 参数

  • 网络慢时点击左边cell右边数据不能及时刷新, 用户看到的还是上一个cell显示的数据

    • 解决办法: 在网络加载之前就reload数据,让显示空白
  • 点击左边的cell时 上拉加载更多控件的显示和隐藏逻辑

    • 解决办法: 在每次刷新右边数据时,控制footer的显示
  • 在numberOfRowsInSection方法中控制

  • 每次点击cell之前要结束上一个没有刷新完的,防止奔溃

  • 加载更多时

    在加载第一页时设置currentPage为1,在加载更多的逻辑中 ++currentPage
    点击cell加载时上一个加载更多的网络数据还没有回来,在当前请求之前结束掉所有的网络请求
    停止之后的刷新控件状态会有错误,没有更多还是还可以加载状态不确定
    在点击左边cell后刷新右边的之前需要检查右边tableView 的footer的状态
    下拉刷新

  • 第一次下拉刷新之后,第二次下拉刷新,将数据添加到数组中会导致两次数据重复

    • 解决办法:清除以前的所有数据
  • 下拉刷新完毕后结束刷新后需要检查footer的状态

  • 网络慢时连续点击cell,连发多个请求成功回调时数据显示错乱,或者是数据已经回来了但是还是显示上一个请求正在请求。。。

    • 解决办法:点击左边某个类别时,结束所有的刷新(上拉和下拉)
  • 连续点击发送请求

    • 解决办法:保存请求参数, 比较上一次参数和当前参数, 如果 != 直接return,不让进入成功回调解析数据, 失败的时候也是同样 return,不提示用户
  • 控制器正在请求数据时控制器销毁, 导致奔溃

    • 解决办法:在dealloc 中停止所有的操作

cell 的frame 设置

  • cell 之间的间隙以及cell的边距 重写frame 在super 之前设置

    • 设置frame 的x ,width, height 等属性
  • 分页的2种做法

    • 下拉刷新

      page 加载最新的 加载第一页 浪费用户的流量
      加载比当前更新的数据, 需要服务器支持,将当前最新的数据id发送给服务器,服务器加载比当前id还大的数据插入到最前面

    • 上拉加载

      将页码发给服务器

      将最后面的数据的id发给服务器,

      加载比当前id更小的数据

Hexo个人博客搭建

安装Homebrew

1
/usr/bin/ruby -e " (curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安装git

1
sudo brew install git

安装node.js

安装hexo

  • 需要输入密码: sudo 管理员权限 -g 全局安装
1
sudo npm install -g hexo

初始化 执行 hexo init 命令

  • 指定安装文件 blog
1
hexo init blog
  • cd 到 文件夹 blog 下,安装 npm
1
npm install
  • 开启服务
1
hexo s

关联 github

  • 添加 ssh key 到github

  • 设置 Mac 显示隐藏文件

    • 在终端执行一下命令后,重启Finder

      1
      defaults write com.apple.finder AppleShowAllFiles -bool true
  • 检查 SSH keys 是否存在 github

    • 打开 Finder 前往(command + shit + G)

      1
      ~/.ssh/id_rsa.pub
  • 如果有文件说明存在 SSH key, 打开 id_rsa.pub 文件,复制里面的信息

  • 进入 Github –> Settings –> SSH keys –> add SSH key
    任意添加一个title 粘贴内容到key 里,点击Add key 绿色按钮即可。

创建名字为 用户名.github.io 的仓库

自行百度。。。。

配置 hexo

  • vim 打开 _config.yml修改 deploy 模块
1
vim _config.yml
1
2
3
4
deploy:
type: git
repository: https://github.com/用户名/用户.github.io.git
branch: master

冒号后需要加空格

生成 hexo 的静态页面

1
hexo generate 后者 hexo g
  • 报以下错
1
2
ERROR Local hexo not found in ~/blog
ERROR Try runing: 'npm install hexo --save'
  • 执行下面代码
1
npm install hexo --save

部署 hexo

1
hexo deploy 或者 hexo d
  • 报以下错误
1
ERROR Deployer not found: git

解决方法:

1
2
npm install hexo-deployer-git --save
hexo d
  • 配置 Deloyment 前,需要配置自己的身份信息
1
2
git config --global user.name "yourname"
git config --global user.email "youremail"

如果执行完以上命令还是不行,删除blog文件下的 .deploy_git 文件重新 hexo deploy