工程中 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字眼,猜测是没网时数据加载不出来需要展示的组件。
怎么去找呢?
- 在你想要找到这个模块中打一个断点,根据名字猜测出大概的位置,然后在模拟器上多点几下试试,如果当前页面触发了断点,那么该页面就调用了此代码模块对应的组件,打开牛牛bate版,找到对应的页面,摇一摇打开3D视图,就能很清楚的看到这个组件的信息了。
- 同时牛牛也是一个庞大的工程,如果像无头苍蝇一样乱点的话,可能点半天也找不到对应的组件,那就要从代码里面的注释去抓敏感信息。
对应第一个方法:以下图片为 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_self
和 ft_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 指向的对象被释放
参考文章
------------- 本文结束 感谢阅读 -------------