Swift常用基础知识(一)

函数式编程

函数合成

func add1(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }func currying<A, B, C>(_ fn: @escaping (A, B) -> C) -> (B) -> (A) -> C {return { b inreturn { a inreturn fn(a, b)}}
}
print(currying(add1)(20)(10))func add(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
func sub(_ v1: Int, _ v2: Int) -> Int { v1 - v2 }
func multiple(_ v1: Int, _ v2: Int) -> Int { v1 * v2 }
func divide(_ v1: Int, _ v2: Int) -> Int { v1 / v2 }
func mod(_ v1: Int, _ v2: Int) -> Int { v1 % v2 }print(currying(add)(20)(100),
currying(sub)(20)(100),
currying(multiple)(20)(100),
currying(divide)(20)(100),
currying(mod)(20)(100))

柯里化(Currying)

prefix func ~<A, B, C>(_ fn: @escaping (A, B) -> C) -> (B) -> (A) -> C {{ b in { a in return fn(a, b) } }
}infix operator >>> : AdditionPrecedence
func >>><A, B, C>(_ fn1: @escaping (A) -> B, _ fn2: @escaping (B) -> C) -> (A) -> C {{ fn2(fn1($0)) }
}
var num = 1
var fn = (~add)(3) >>> (~multiple)(5) >>> (~sub)(1) >>> (~mod)(10) >>> (~divide)(2)
print(fn(num))
print((((num+3)*5 - 1) % 10) / 2)func add2(_ v1: Int, _ v2: Int, _ v3: Int) -> Int { v1 - v2 + v3 }
prefix func ~<A, B, C, D>(_ fn: @escaping (A, B, C) -> D) -> (C) -> (B) -> (A) -> D {{ c in { b in { a in return fn(a, b, c) } } }
}
//20
print((~add2)(30)(20)(10)

函子(Functor)

  • 像Array、 Optional这样支持map允许的类型,称为函子(Functor)
public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
  • Functor is the Type Justlike have this method
func map<T>(_ fn: (Inner) -> T) -> Type<T>

适用函子(Applicative Functor)

  • 对人员一个函子F,如果能支持一下运算,该函子就是一个适用函子
//func pure<T>(_ value: T) -> F<T>
//func <*><A, B>(_ fn: F<(A) -> B>, _ value: F<A>) -> F<B>
  • Array可以成为适用函子
func pure<T>(_ value: T) -> T? { value}
infix operator <*> : AdditionPrecedence
func <*><A, B>(_ fn: ((A) -> B)?, _ value: A?) -> B? {guard let f = fn, let v = value else { return nil}return f(v)
}var value: Int? = 10
var fn: ((Int) -> Int)? = { $0 * 2 }
Optional(20)
print(fn <*> value as Any)

//Optional可以成为适用函子

func pure<T>(_ value: T) -> [T] { [value] }
func <*><A, B>(_ fn: [(A) -> B], _ value: [A]) -> [B] {var array: [B] = []if fn.count == value.count {for i in fn.startIndex..<fn.endIndex {array.append(fn[i](value[i]))}}return array
}
//[10]
print(pure(10))
var array = [{ $0 * 2}, { $0 + 10 }, { $0 - 5}] <*> [1, 2, 3]
//[2, 12, -2]
print(array)

单子(Monad)

  • 对任意一个类型F,如果嫩支持以下运算,那么就可以称为是一个单子(Monad)
func pure<T>(_ value: T) -> F<T>
func flatMap<A, B>(_ value: F<A>, _ fn: (A) -> F<B>) -> F<B>
  • 很显然Array、 Optional都是单子

面向协议编程

■ 面向协议编程( Protocol Oriented Programming ,简称POP )

  • 是Swift的一种编程范式,Apple于2015年WWDC提出
  • 在Swift的标准库中,能见到大量POP的影子
    ■ 同时, Swift也是一-门面向对象的编程语言( Object Oriented Programming ,简称OOP )
  • 在Swift开发中, OOP和POP是相辅相成的,任何一方并不能取代另一方
    ■ POP能弥补OOP-些设计上的不足

回顾OOP

■ OOP的三大特性:封装、继承、多态
■ 继承的经典使用场合

  • 当多个类(比如A、B、C类)具有很多共性时,可以将这些共性抽取到一个父类中(比如D类) , 最后A、B、C类继承D类

OOP的不足

■ 但是有些问题,使用OOP并不能很好解决

  • 如何将BVC、AVC的公共方法run抽取出来?
class BVC: UIViewController {func run() {print("run")}
}
class AVC: UIViewController {func run() {print("run")}
}

■ 基于OOP想到的一些解决方案?
1.将run方法放到另一个对象A中,然后BVC、DVC拥有对象A属性

  • 多了一些额外的依赖关系
    2.将run方法增加到UIViewController分类中
  • UIViewController会越来越臃肿,而且会影响它的其他所有子类
    3.将run方法抽取到新的父类,采用多继承? ( C++支持多继承 )
  • 会增加程序设计复杂度,产生菱形继承等问题,需要开发者额外解决

POP的解决方案

protocol Runnable {func run()
}
extension Runnable {func run() {print("run")}
}
class AVC: UIViewController, Runnable {}
class BVC: UIViewController, Runnable {}

POP的注意点

■ 优先考虑创建协议,而不是父类(基类)
■ 优先考虑值类型(struct、enum), 而不是引用类型( class )
■ 巧用协议的扩展功能
■ 不要为了面向协议而使用协议

利用协议实现前缀效果

struct HY<Base> {let base: Baseinit(_ base: Base) { self.base = base }
}
protocol HYCompatible {}
extension HYCompatible {static var hy: HY<Self>.Type {get { HY<Self>.self }set {}}var hy: HY<Self> {get { HY(self) }set {}}
}
extension String: HYCompatible {}
extension HY where Base == String {var numberCount: Int {var count = 0for c in base where ("0"..."9").contains(c) {count += 1}return count}static func test() {print("\(Self.self) static")}
}
var string = "123qwe434"
// 6
print(string.hy.numberCount)
//HY<String> static
print(String.hy.test())
class Person {}
extension Person: HYCompatible {}
extension HY where Base: Person {func run() {print("\(self) run")}static func test() { print("\(Self.self) static func") }
}
class Teacher: Person {}
extension HY where Base == Teacher {func teach() {print("teach")}
}
//HY<Person> static func
Person.hy.test()
//HY<Teacher> static func
Teacher.hy.test()
let p = Person()
//HY<Person>(base: Adam_20220925_SwiftBase.Person) run
p.hy.run()
let t = Teacher()
//HY<Teacher>(base: Adam_20220925_SwiftBase.Teacher) run
t.hy.run()

给NSString加前缀

extension NSString: HYCompatible {}
extension HY where Base: NSString {var numberCount: Int {var count = 0for c in base as String where ("0"..."9").contains(c) {count += 1}return count}
}
var string1 = "123XXX"
var string2: NSString = "123XXX"
var string3: NSMutableString = "123XXX"
print(string1.hy.numberCount)
print(string2.hy.numberCount)
print(string3.hy.numberCount)

给NSString加前缀优化

extension String: HYCompatible {}
extension NSString: HYCompatible {}extension HY where Base: ExpressibleByStringLiteral {var numberCount: Int {var count = 0for c in (base as! String) where ("0"..."9").contains(c) {count += 1}return count}
}
var string1 = "123XXX"
var string2: NSString = "1234XXX"
var string3: NSMutableString = "12345XXX"
print(string1.hy.numberCount)
print(string2.hy.numberCount)
print(string3.hy.numberCount)

利用协议判断类型

protocol ArrayType {}
extension Array: ArrayType {}
extension NSArray: ArrayType {}
func isArrayType(_ type: Any.Type) -> Bool {type is ArrayType.Type
}
print(isArrayType([Int].self))
print(isArrayType([Double].self))
print(isArrayType([Any].self))
print(isArrayType(NSArray.self))
print(isArrayType(NSMutableArray.self))
print(isArrayType(String.self))

响应式编程

响应式编程( Reactive Programming ,简称RP )

  • 也是y一种编程范式,于1997年提出,可以简化异步编程,提供更优雅的数据绑定
  • 一般与函数式融合在一起,所以也会叫做:函数响应式编程( Functional Reactive Programming,简称FRP )
    比较著名的、成熟的响应式框架

❇️ ReactiveCocoa :

  • 简称RAC ,有Objective-C、 Swift版本
  • 官网:,http://reactivecocoa.iol
  • github: https://github.com/ReactiveCocoa

❇️ ReactiveX

  • 简称Rx ,有众多编程语言的版本,比如RxJava、 RxKotlin、 RxJS. RxCpp、 RxPHP、 RxGo、 RxSwift等等
  • 官网:http://reactivex.io/
  • github: https://github.com/ReactiveX

RxSwift

■ RxSwift ( ReactiveX for Swift ) , ReactiveX的Swift版本

  • 源码: https://github.com/ReactiveX/RxSwift
  • 中文文档: https://beeth0ven.github.io/RxSwift-Chinese-Documentation/

■ RxSwift的安装
①Podfile
use_ frameworks!
target ‘target_ name’ do
pod ‘RxSwift’, ‘~> 6’
pod ‘RxCocoa’, ‘~> 6’
end

②命令行
pod repo update
pod install
③导入模块
import RxSwift
import RxCocoa

■ 模块说明

  • RxSwift : Rx标准API的Swift实现,不包括任何iOS相关的内容
  • RxCocoa :基于RxSwift ,给iOS UI控件扩展了很多Rx特性

RxSwift核心类

  • Observable:负责发送事件(Event)
  • Observer: 负责订阅Observable,监听Observable发送的事件

Event 类型

/// **next\* (error | completed)**
@frozen public enum Event<Element> {/// Next element is produced.case next(Element)/// Sequence terminated with an error.case error(Swift.Error)/// Sequence completed successfully.case completed
}

创建、订阅observable1


//        let observable = Observable<Int>.create { observer in
//            observer.onNext(1)
//            observer.onCompleted()
//            return Disposables.create()
//        }
// 等价于
//        let observable = Observable.just(1)
//        let observable = Observable.of(1)let observable = Observable.from([1])observable.subscribe{ event inprint(event)}.dispose()
//        let observable = Observable<Int>.create { observer in
//            observer.onNext(1)
//            observer.onNext(2)
//            observer.onNext(3)
//            observer.onCompleted()
//            return Disposables.create()
//        }
// 等价于
//        let observable = Observable.of(1, 2, 3)let observable = Observable.from([1, 2, 3])observable.subscribe{ event inprint(event)}.dispose()observable.subscribe {print("next", $0)} onError: {print("onError", $0)} onCompleted: {print("onCompleted")} onDisposed: {print("onDisposed")}.dispose()// 等价于observable.subscribe (onNext: {print("next", $0)}, onError: {print("onError", $0)}, onCompleted: {print("onCompleted")}, onDisposed: {print("onDisposed")}).dispose()

创建、订阅observable2

let observable = Observable<Int>.timer(.seconds(3),period: .seconds(1),scheduler: MainScheduler.instance)observable.map{ "数值为\($0)"}.bind(to: label.rx.text).disposed(by: bag)

Disposable

    ■每当Observable被订阅时,都会返回一个Disposable实例,当调用Disposable的dispose ,就相当于取消订阅■在不需要再接收事件时,建议取消订阅,释放资源。有3种常见方式取消订阅
       let observable = Observable.from([1, 2, 3])//立即取消订阅(一次性订阅)observable.subscribe { event inprint (event )}.dispose()//当bag销毁(deinit) 时,会自动调用Disposab le实例的disposeobservable.subscribe { event inprint(event)}.disposed(by: bag)// self销毁时(deinit) 时,会自动调用Disposable实例的disposelet _ = observable.takeUntil(self.rx.deallocated).subscribe { event inprint(event)}

Binder Label

let binder = Binder(label) { label, value inlabel.text = value}Observable.just(1).map { "数值为\($0)" }.subscribe(binder).dispose()Observable.from([1, 2, 3]).map { "数值为\($0)" }.bind(to: binder).dispose()

Binder UIButton

        let observable = Observable<Int>.timer(.seconds(2),period: .seconds(1),scheduler: MainScheduler.instance)let binder = Binder<Bool>(button) { button, value inbutton.isHidden = value}observable.map { $0 % 2 == 0}.bind(to: binder).disposed(by: bag)

Swift常用基础知识(二)相关推荐

  1. 网络基础知识(二) HTTP

    网络基础知识(二) HTTP 黑发不知勤学早,白首方悔读书迟. 内容参考:https://www.runoob.com/http/http-content-type.html HTTP协议是Hyper ...

  2. CV:计算机视觉技术之图像基础知识(二)—图像内核的可视化解释

    CV:计算机视觉技术之图像基础知识(二)-图像内核的可视化解释 目录 图像内核的可视化解释 测试九种卷积核 官方Demo DIY图片测试 DIY实时视频测试 相关文章 CV:计算机视觉技术之图像基础知 ...

  3. CV:计算机视觉技术之图像基础知识(二)—以python的skimage和numpy库来了解计算机视觉图像基础(图像存储原理-模糊核-锐化核-边缘检测核,进阶卷积神经网络(CNN)的必备基础)

    CV:计算机视觉技术之图像基础知识(二)-以python的skimage和numpy库来了解计算机视觉图像基础(图像存储原理-模糊核-锐化核-边缘检测核,进阶卷积神经网络(CNN)的必备基础) 目录 ...

  4. (五)JS基础知识二(通过图理解原型和原型链)【三座大山之一,必考!!!】

    JS基础知识二(原型和原型链) 提问 class 继承 类型判断(instanceof) 原型 原型关系 基于原型的执行规则 原型链 说明 提问 如何准确判断一个变量是不是数组 class的原型本质 ...

  5. 网络服务器最基本的是文件,你可能想知道的15个网络常用基础知识

    原标题:你可能想知道的15个网络常用基础知识 网络是一个复杂的系统,涉及知识很多.现在腾正小超人给大家分享15个常用的网络基础知识: 1) 如何查看本机所开端口 用netstat -a -n命令查看! ...

  6. oracle:oracle基础知识(二)

    oracle基础知识(二)笔记:高级查询 文章目录 分组查询 多属性分组语法: 过滤查询 group by 语句增强 sqlplus报表功能 多表查询 等值连接 外连接 自连接 子查询 子查询中的空值 ...

  7. Linux常用基础知识必备三之常用指令及操作

    Linux常用基础知识必备三之常用指令及操作 1.vi和vim vi如何使用 vi几种模式下的操作指令 命令模式进入编辑模式 命令模式下的快捷键 底行模式(指按了esc键之后输入按键:后出现) 字符串 ...

  8. CV:计算机视觉技术之图像基础知识(二)—图像内核的九种卷积核可视化解释(blur/bottom sobel /emboss/identity /sobel /outline/sharpen)

    CV:计算机视觉技术之图像基础知识(二)-图像内核的九种卷积核可视化解释(blur/bottom sobel /emboss/identity /left sobel /outline/right s ...

  9. scikit-learn学习基础知识二

    scikit-learn学习基础知识二 文章目录 scikit-learn学习基础知识二 一.介绍 二.代码实现 三.运行结果 四.总结 一.介绍 本文我们学习scikit-learn中的KNeigh ...

最新文章

  1. linux备份svn仓库脚本,Centos详细搭建svn以及备份脚本
  2. 第三代基因测序技术革新 云计算的应用
  3. 三年51亿!30岁的TA携「三瑞」打通场景级智慧,走入极「智」医疗
  4. 如何产生QPSK信号
  5. 解密春晚微信红包十亿级并发压力
  6. python求回数_用python求回数
  7. Haar特征与积分图—概念解析
  8. Python天天美味(35) - 细品lambda(转)
  9. 一篇文章让你学透Linux系统中的more命令
  10. 路由器刷机突破校园网限制
  11. java使用RXTX的详细总结
  12. java解析数组_Java解析Json数组对象
  13. 如何用计算机录视频,如何在电脑上录制正在播放的视频?原来方法这么简单
  14. 英语口语 每日一句 小红书TroyChina
  15. 【转载】django-数据库[ 配置 ]
  16. python对比两张图片的不同并圈起来,比较两幅图像/图片,并标记差异
  17. 计算机价格谈判议程,谈判议程
  18. 《“ 追梦人” 的逐梦路:探寻大学生创客群体的发展之道》
  19. HCIE课程笔记18-局域网二层技术
  20. 等额本金和等额本息两种贷款方式的比较

热门文章

  1. 论坛议程|COSCon'22 女性论坛(L)
  2. 简单名称值对节点类NameValuePair
  3. Ansible的task执行方式控制:forks以及serial
  4. BCryptPasswordEncoder 对密码加密
  5. 为什么最好是选择付费的代理IP而不是免费的代理IP?
  6. Python爬虫:scrapy辅助功能实用函数
  7. Office宏——打印PPT
  8. 亚马逊---【运维工程师】实习生面试心得
  9. 苹果cms怎么批量替换无法播放的资源地址
  10. Linux erlang 源码编译安装