长路漫漫,唯剑作伴--总结

时间:2021-01-17 05:34:18

一、block

  1️⃣、简介

  2️⃣、一个简单的block

  3️⃣、结合tepydef使用,作为属性实现传值

  4️⃣、内存管理

二、代理

  1️⃣、简介

  2️⃣、基本使用:协议定义,代理方遵守协议,委托方判断代理方是否实现协议方法

  3️⃣、实现多继承

  4️⃣、控制器瘦身

  5️⃣、内存管理

三、NSThread

  1️⃣、简介

  2️⃣、线程创建:静态,动态,隐式

  3️⃣、线程通信:主线程执行、当前线程执行、指定线程执行

  4️⃣、线程同步:NSLock、NSCondition、@synchronized

四、NSOperation

  1️⃣、简介:NSOperation是一个抽象基类,因此如果想要使用NSOperation,需要使用到其两个子类NSinvocationOperation、NSBlockOperation,或者自定义Operation;

  2️⃣、NSinvocationOperation:创建

  3️⃣、NSBlockOperation:创建、添加操作

  4️⃣、自定义NSOperation:需要正确的取消操作

  5️⃣、线程控制:取消、开始、监听、添加依赖关系和优先级

  6️⃣、结合NSOperationQueue使用:暂停和继续

五、GCD

  1️⃣、队列和操作

  2️⃣、串行队列、并行队列:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),dispatch_get_main_queue(),dispatch_queue_create("xiaozhu", DISPATCH_QUEUE_SERIAL,dispatch_queue_create("......", DISPATCH_QUEUE_CONCURRENT);

  3️⃣、同步和异步

  4️⃣、死锁

NSLog(@"1"); // 任务1
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3

  5️⃣、新方式创建单例

    + (AccountManager *)sharedManager  
    {  
            static AccountManager *sharedAccountManagerInstance = nil;  
            static dispatch_once_t predicate;  
            dispatch_once(&predicate, ^{  
                    sharedAccountManagerInstance = [[self alloc] init];   
            });  
        return sharedAccountManagerInstance;  
    }  

 六、Webkit

  1️⃣、四种交互方式:WKUIDelegate,WKUserScript注入、WKScriptMessageHandler,- (void)evaluateJavaScript: completionHandler:

  2️⃣、JS调用本地方法:- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

//插入html    getElementsByTagName 根据html自带标签定位元素
- (IBAction)insertHtmTouched:(id)sender {
    //插入整个页面内容
    // document.getElementsByTagName('body')[0];"
    
    //替换第一个P元素内容
    NSString *tempString = [NSString stringWithFormat:@"document.getElementsByTagName('p')[0].innerHTML ='%@';",self.someString];
    [self.myWebView evaluateJavaScript:tempString  completionHandler:^(id item, NSError * _Nullable error) {
        
    }];
}

 

七、UIWebVIew

  1️⃣、JS调用本地方法:- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

  2️⃣、本地调用JS:- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

// 插入html       根据getElementById 定位元素
- (IBAction)insertDivHtml:(id)sender {
    
    //替换第id为idtest的DIV元素内容
    NSString *tempString2 = [NSString stringWithFormat:@"document.getElementById('idTest').innerHTML ='%@';",self.someString];
    [self.myWeb stringByEvaluatingJavaScriptFromString:tempString2];
   

 八、项目架构

  长路漫漫,唯剑作伴--总结

九、UITableViewCell上有个UILabel,显示NSTimer实现的秒表时间,手指滚动cell过程中,label是否刷新,为什么?

  这是否刷新取决于timer加入到Run Loop中的Mode是什么。Mode主要是用来指定事件在运行循环中的优先级的,分为:

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
  • UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode
  • UIInitializationRunLoopMode:run loop启动时,会切换到该mode
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合

   苹果公开提供的Mode有两个

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
  • NSRunLoopCommonModes(kCFRunLoopCommonModes)

  如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。当我们滚动的时候,也希望不调度,那就应该使用默认模式。但是,如果希望在滚动时,定时器也要回调,那就应该使用common mode。

  对于这道题,如果要cell滚动过程中定时器正常回调,UI正常刷新,那么要将timer放入到CommonModes下,因为是NSDefaultRunLoopMode,只有在空闲状态下才会回调。

  NSTimer传送门

十、UIBezeirPath、CAShapLayer

  

说到CAShapLayer就不得不说到UIBezierPath: UIBezierPath是在 UIKit 中的一个类,继承于NSObject,可以创建基于矢量的路径。使用此类可以定义常见的圆形、多边形等形状 。我们使用直线、弧(arc)来创建复杂的曲线形状。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。

CAShapeLayer: CAShapeLayer顾名思义,继承于CALayer。 每个CAShapeLayer对象都代表着将要被渲染到屏幕上的一个任意的形状(shape)。具体的形状由其path(类型为CGPathRef)属性指定。 普通的CALayer是矩形,所以需要frame属性。CAShapeLayer初始化时也需要指定frame值,但 它本身没有形状,它的形状来源于其属性path 。CAShapeLayer有不同于CALayer的属性,它从CALayer继承而来的属性在绘制时是不起作用的。

步骤:
1、新建UIBezierPath对象bezierPath
2、新建CAShapeLayer对象caShapeLayer
3、将bezierPath的CGPath赋值给caShapeLayer的path,即caShapeLayer.path = bezierPath.CGPath
4、把caShapeLayer添加到某个显示该图形的layer中

UIBezierPath * path = [[UIBezierPath alloc]init];
[path addArcWithCenter:CGPointMake(self.view.center.x, 175) radius:25 startAngle:0 endAngle:2*M_PIclockwise:NO(如果不是一个闭合的圆,显示顺时针部分还是逆时针的部分)];  画圆
[path moveToPoint:CGPointMake(self.view.center.x, 200)];  画笔移到某个点
[path addLineToPoint:CGPointMake(self.view.center.x, 250)];  划直线

self.layer1 = [CAShapeLayer layer];
self.layer1.path = path.CGPath;
self.layer1.lineWidth = 10;
self.layer1.fillColor = [UIColor clearColor].CGColor;
self.layer1.strokeColor = [UIColor blackColor].CGColor;
self.layer1.lineCap = kCALineCapRound;
[self.view.layer addSublayer:self.layer1];

 十一、上线问题

  传送

十二、CALayer和UIView

  1、在说CALayer和UIView有什么不同时,首先说明其关系。

  2、当创建一个UIView对象时,其内部会自动创建一个层(CALayer对象),通过UIView的layer属性,可以访问到这个层。当UIView需要显示的屏幕上时,会调用其drawRect:方法进行绘制,并且将所有的内容绘制到这个层上。绘图完毕后,再将其拷贝到屏幕上,完成UIView的显示。换句话说,UIView不具备显示的功能,其内部的层才具备显示功能。

  3、UIVIew继承自UIResponder,而CALayer继承自NSObject。

  4、改变CALayer的一些属性,比如corners、position、opacity等,会产生隐式动画,而UIView不会。

  5、UIView可以响应触摸事件,而CALayer不会。

  6、UIView侧重于内容的管理,CALayer侧重于内容的绘制。