工程中 QuoteUtil文件夹阅读笔记

工程中QuoteUtil文件夹阅读笔记

[toc]

基本信息

目录结构:

.
├── ColorManager
├── FTEmptyTableViewCell.h
├── FTEmptyTableViewCell.m
├── FTEmptyTableViewCell.xib
├── FTQuoteAlertUtil.swift
├── FTQuoteCustomEmptyFailedView.h
├── FTQuoteCustomEmptyFailedView.m
├── FTQuoteCustomEmptyNoDataView.h
├── FTQuoteCustomEmptyNoDataView.m
├── FTQuoteCustomLoadingEmptyDataSetView.h
├── FTQuoteCustomLoadingEmptyDataSetView.m
├── FTQuoteCustomLoadingView.h
├── FTQuoteCustomLoadingView.m
├── FTQuoteStockNewsMiniView.h
├── FTQuoteStockNewsMiniView.m
├── FTQuoteUtil.h
├── FTQuoteUtil.m
├── FTSensorsTimeTrackManager.h
├── FTSensorsTimeTrackManager.m
└── UIImage+Share.swift

模块对应组件

上面这些代码对应的都是牛牛中的什么组件?其实看名字也能猜出个大概,文件名中很多都有Empty字眼,猜测是没网时数据加载不出来需要展示的组件。

怎么去找呢?

  1. 在你想要找到这个模块中打一个断点,根据名字猜测出大概的位置,然后在模拟器上多点几下试试,如果当前页面触发了断点,那么该页面就调用了此代码模块对应的组件,打开牛牛bate版,找到对应的页面,摇一摇打开3D视图,就能很清楚的看到这个组件的信息了。
  2. 同时牛牛也是一个庞大的工程,如果像无头苍蝇一样乱点的话,可能点半天也找不到对应的组件,那就要从代码里面的注释去抓敏感信息。

对应第一个方法:以下图片为 FTQuoteCustomLoadingEmptyDataSetView 对应的组件

对应第二个方法:

看到代码中有“资讯”两字,就应该去资讯页去找对应的组件

代码片段解读

futunn/ftphonequote/Business/Quote/QuoteUtil/FTQuoteCustomLoadingEmptyDataSetView.m

- (FTQuoteCustomEmptyFailedView *)failedView {
    if (!_failedView) {
        _failedView = [[FTQuoteCustomEmptyFailedView alloc] init];
        _failedView.contentEdgeTopInset = self.contentEdgeTopInset;
        ft_weakify_self;
        _failedView.didClickButtonBlock = ^(UIButton * _Nonnull button) {
            ft_strongify_self;
            if ([self.delegate respondsToSelector:@selector(emptyDataSetView:didTapButton:)]) {
                [self.delegate emptyDataSetView:self didTapButton:button];
            }
        };
    }
    return _failedView;
}

这里的 ft_weakify_selfft_strongify_self 是什么意思呢?为什么要在block前一行和block里面调用这个东西呢?

点进去一看,发现 ft_weakify_self 就是 @weakify(self)

//
//  FTWeakHelper.h
//  FTCocoaDevelopKit
//
//  Created by jenson on 2018/10/26.
//  Copyright © 2018年 FUTU. All rights reserved.
//

#ifndef FTWeakHelper_h
#define FTWeakHelper_h

#import "EXTScope.h"

#define ft_weakify_self  @weakify(self)

#define ft_strongify_self \
@strongify(self); \
if (self == nil) { \
return ; \
}

#define ft_strongify_self_nil_return(returnValue) \
@strongify(self); \
if (self == nil) { \
return returnValue; \
}


#endif /* FTWeakHelper_h */

为什么会有这么多换行符呢?

首先来了解下宏的一些基本东西

- 程序第一步是在预编译之前会有一些操作, 例如删除反斜线和换行符的组合, 将每个注释用一个空格替代...,
- 然后在进入预编译的时候, 会寻找可能存在的预处理指定(由#开头), 例如C中常用的#include, 或者oc中的#import, #define...很多(条件编译语句...)
- 处理#define的时候,然后预处理器会从#开始, 一直到执行到第一个换行符(写代码的时候换行的作用), 自然, #define只会允许定义一行的宏, 不过正因为上面提到的预处理之前会删除反斜线和换行符的组合, 所以可以利用反斜线定义多行宏, 在删除反斜线和换行符的组合后, 逻辑上就成了一行的宏了
- 宏作用在预编译时期, 其真正的效果就是代码替换, 而且是直接替换(内联函数!!!), 这个和函数有着很大的区别, 并且正因为是直接替换, 在使用的时候就需要注意了
- 宏可以被称为 类对象宏, 类函数宏
- 宏在预处理阶段只进行文本的替换(相当于把代码拷贝粘贴), 不会进行具体的计算(发生在编译时期)

了解了这个我们再来回答:为什么要在block前一行和block里面调用这个东西呢?

来看一下一个循环引用的例子:假设一个对象有一个强引用的 block 属性,同时此 block 通过 self 指针访问了该对象的其它属性,这将导致 block 也对该对象进行了强引用。这样的话会引起内存泄露,block和当前对象都无法释放。

所以 ft_weakify_self 的作用是:block 对 self 是弱引用引用,打破了循环引用的闭环

ft_strongify_self 的作用是:避免 block 代码执行一半,self 指向的对象被释放

参考文章

一篇文章搞懂 @weakify 和 @strongify

介绍iOS中@strongify和@weakify

IOS-OC-@synthesize 的作用

------------- 本文结束 感谢阅读 -------------