ARTS-11.08

Algorithm

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/submissions/

从第二天的价格开始,若比第一天价格高,总收益就加上这两天的价格差

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution122 {
func maxProfit(_ prices: [Int]) -> Int {
var maxProfit = 0
var day = 1
while day < prices.count {
if prices[day] - prices[day - 1] > 0 {
maxProfit += (prices[day] - prices[day - 1])
}
day += 1
}
return maxProfit
}
}

Review

2. 整体把握 CocoaPods 核心组件

CocoaPods的核心组件有:

  • CLAide

    • 命令行解释器。它不仅负责解析我们使用到的 Pods 命令,如:pod install, pod update 等,还可用于封装常用的一些脚本,将其打包成简单的命令行小工具。
  • cocoapods-core

    • 用于 CocoaPods 中模板文件的解析,包括 Podfile.podspec,以及所有的 .lock 文件中特殊的 YAML 文件。
  • cocoapods-downloader

    • 是用于下载源码的小工具,它支持各种类型的版本管理工具,包括 HTTP / SVN / Git / Mercurial。
    • 它可以提供 tagscommitesrevisionsbranches 以及 zips 文件的下载和解压缩操作。
  • Molinillo

    • 是 CocoaPods 对于依赖仲裁算法的封装,它是一个具有前向检查的回溯算法。
    • 不仅在 Pods 中,BundlerRubyGems 也是使用的这一套仲裁算法。
  • Xcodeproj

    • 可通过 Ruby 来操作 Xcode 项目的创建和编辑等。
    • 可友好的支持 Xcode 项目的脚本管理和 libraries 构建,以及 Xcode 工作空间.xcworkspace 和配置文件 .xcconfig 的管理。
  • cocoapods-plugins

    • 插件管理功能,其中有 pod plugin 全套命令,支持对于 CocoaPods 插件的列表一览(list)、搜索(search)、创建(create)功能。

pod install 处理流程

  • 命令入口

    • 在本地/bin目录下找到pod命令
    • pod命令的功能:命令转发,通过Gem.activate_bin_pathGem.bin_path 找到 CocoaPods 的安装目录 cocoapods/bin,最终加载该目录下的 /pod 文件。
      • 通过调用 Pod::Command.run(ARGV),实例化了一个 CLAide::Command 对象,开始 CLAide 命令解析阶段
  • 执行功能主体

    1. Install 环境准备(prepare)

      • 版本一致性目录结构以及将 pre-install 的装载插件脚本全部取出,并执行对应的 pre_install hook
    2. 解决依赖冲突(resolve_dependencies)

      • 通过 PodfilePodfile.lock 以及沙盒中的 manifest 生成 Analyzer 对象。Analyzer 内部会使用 Molinillo::DependencyGraph 图算法解析得到一张依赖关系表。
      • 解决当我们在通过 Git 地址引入的 Pod 仓库的情况下,系统无法从默认的 Source 拿到对应的 Spec,需要直接访问我们的 Git 地址下载仓库的 zip 包,并取出对应的 podspec 文件,从而进行对比分析。
      • 此过程中有一个 pre_download 的阶段,即在 –verbose 下看到的 Fetching external sources 过程。这个 pre_download 阶段不属于依赖下载过程,而是在当前的依赖分析阶段。
    3. 下载依赖文件(download_dependencies)

      • create_file_accessors 中会创建沙盒目录的文件访问器,通过构造 FileAccessor 实例来解析沙盒中的各种文件。
      • 接着是最重要的 install_pod_sources 过程,它会调用对应 Pod 的 install! 方法进行资源下载。
    4. 验证 targets (validate_targets)

      • 构造 TargetValidator,并执行 validate! 方法,验证之前流程中的产物 (pod 所生成的 Targets) 的合法性。

      • 验证内容:

        • verify_no_duplicate_framework_and_library_names

          验证是否有重名的 framework

        • verify_no_static_framework_transitive_dependencies

          验证动态库中是否有静态链接库 (.a 或者 .framework) 依赖。

        • verify_swift_pods_swift_version

          确保 Swift Pod 的 Swift 版本正确配置且互相兼容的。

        • verify_swift_pods_have_module_dependencies

          检测 Swift 库的依赖库是否支持了 module。

        • verify_no_pods_used_with_multiple_swift_versions

          检测是否所有的 Pod Target 中版本一致性问题。

    5. 生成工程 (Integrate)

      • 将之前版本仲裁后的所有组件通过 Project 文件的形式组织起来,并且会对 Project 中做一些用户指定的配置。
    6. 写入依赖 (write_lockfiles)

      • 将依赖更新写入 Podfile.lockManifest.lock
    7. 结束回调(perform_post_install_action)

Tips

验证码倒计时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取验证码请求发送成功后,调用下面函数
public func startCoolingTimeScheduler() {
self.sendButton.isEnabled = false
Observable<Int>.timer(RxTimeInterval.seconds(0), period: RxTimeInterval.seconds(1), scheduler: MainScheduler.instance)
.map { 60 - $0 }
.takeWhile { $0 > 0 }
.subscribe(onNext: { [weak self] (remind) in
guard let self = self else { return }
self.sendButton.setTitle("重新发送(\(remind)s)", for: .disabled)
}, onCompleted: { [weak self] () in
guard let self = self else { return }
self.sendButton.isEnabled = true
}).disposed(by: self.bag)
}

正则匹配“字母/数字/特殊符号至少包含2种”

1
2
3
4
5
func isContainTwoTypeCharPassword() -> Bool {
let pattern = "^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?![^[0-9]a-zA-Z]+$).{8,20}$"
let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
return predicate.evaluate(with: self)
}

正则:

  • ^在方括号外面:匹配字符串的开始
  • ^在方括号中间:不接受所在方括号中的字符
  • $ 匹配字符串的结束
  • ( ) 子表达式的开始和结束
  • 匹配指定字符
  • {n, m} 限定符,将前面的字符匹配n~m次
  • ?! exp1(?!exp2):查找后面不是 exp2 的 exp1。
  • . 匹配除换行符以为的单个字符
    • 将前面的表达式匹配一次或多次

CombineLatest中的属性要从可选值改为非可选值

1
2
3
4
Observable.combineLatest(
textField1.rx.text.map { $0 ?? ""},
textField2.rx.text.map { $0 ?? ""}
)

给有阴影效果的view设置clipToBounds会导致阴影失效

Share

How to set cornerRadius for only some corners

  • 在iOS11以上,可以用CALayer的maskedCorners属性来配置:view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

  • 在iOS11之前,可以用UIBezierPath设置layer的mask的path来配置:

  • let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 20, height: 20)) 
    let mask = CAShapeLayer()
    mask.path = path.cgPath 
    view.layer.mask = mask
    <!--4-->
    
0%