目录
前端时间在使用RxSwift的时候经常遇到看着像闭包的语法,但是因为结尾没有(),所以又不是,今天温习了一下swift 5.1的基础语法,发现原来是计算属性的只读缩略写法.
先来看下我遇到的语法,下面的语法我知道是把subItem的值赋值给obItem,看着像懒加载的语法,但是实际上是最简单的计算属性缩写
fileprivate var subItem = PublishSubject<String>()
public var obItem:Observable<String> {
subItem
}
上面的代码写全了就是,因为是只读计算属性,所以省略了get,直接在{ }里面返回了计算属性的get的值.
fileprivate var subItem = PublishSubject<String>()
public var obItem:Observable<String> {
get{
subItem
}
}
计算属性的基本语法和注意点
语法格式:
var 变量名字:类型{
get{
返回的值
}
set{
设置的值
}
}
计算属性自己没有存储属性的那样的空间,get{}里面的返回值,是通过计算其他存储属性得到的动态值
下面代码计算属性IdName的返回值是把存储属性name 添加了字符串"Id"再返回, 设置set值里面的newValue是个关键字,就是在外面给IdName赋值的时候,赋值的值就是newValue
class CC: NSObject {
var name:String
var IdName:String{
get{
"Id" + name
}
set{
name = newValue //外面给IdName赋值的时候,赋值的值就是newValue,把外面赋值的值赋值给name,保存起来.
}
}
init(name:String) {
self.name = name
}
}
看下调用代码:
let c = CC(name: "zhangsan")
print("c.IdName=",c.IdName)
print("c.name=",c.name)
c.IdName = "li4"
print("IdName=",c.IdName)
print("name=",c.name)
运行结果:
c.IdName= Idzhangsan
c.name= zhangsan
IdName= Idli4
name= li4
必须用var 来修饰计算属性,不能使用let,因为计算属性会随时改变
下面代码是错误示范,把计算属性用let来修饰,编译报错’let’ declarations cannot be computed 编译错误let不能定义计算属性
class CA: NSObject {
var city :NSString
let Idcity:String{ //计算属性,只有get方法,可以省略get{}//编译错误let不能定义计算属性'let' declarations cannot be computed properties
get{
return city as String
}
}
}
只读计算属性,可以省略get关键字
下面代码跟上面代码完全一样,只是省略了get{}
class CA: NSObject {
var city :NSString
let Idcity:String{ //计算属性,只有get方法,可以省略get{}//编译错误let不能定义计算属性'let' declarations cannot be computed properties
city as String//这里相当于get{ city as String }
}
}
RxSwift中 PublishSubject 可以转换为Observable ,反过来Observable不能赋值给PublishSubject
import UIKit
import RxSwift
import RxCocoa
class CB: NSObject {
fileprivate var subItem = PublishSubject<String>()
public var obItem:Observable<String> {
subItem//把PublishSubject转换为Observable返回
}
func testConvert() {
var ob1 = Observable<Int>.create { (ob) -> Disposable in
ob.onNext(1)
ob.onNext(2)
ob.onCompleted()
return Disposables.create()
}
var sub1 = PublishSubject<Int>()
ob1 = sub1//把PublishSubject转换为Observable
// sub1 = ob1 //不能把序列Observable转换为PublishSubject,因为Observable,不能在创建之后onNext发送信息.只能在create里面发送onNext
}
}
在RxSwift里面计算属性的应用
下面的这个View1在外接访问的时候只能访问obItem,因为是:Observable,所以只能被订阅,不能发送,但是在当前View1内,就可以使用存储属性subItem发送,计算属性obItem是Observable类型,get方法是直接把subItem返回,PublishSubject 和Observable 这2个类型是可以相互赋值的.
//
// View1.swift
// CalculatePropertyDemo
//
// Created by tdw on 2021/3/20.
//
import UIKit
import RxSwift
import RxCocoa
class View1: UIView,TDWXIBSet {
@IBOutlet weak var tf: UITextField!
fileprivate var subItem = PublishSubject<String>()
public var obItem:Observable<String> {
get{
subItem
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setXib()
setUI()
}
func setUI(){
// tf.rx.text.orEmpty.bind(to: obItem)//不能绑定给Observable,因为Observable只能被订阅,不能改变值,所以不能bind
tf.rx.text.orEmpty.bind(to: subItem)//可以绑定到PublishSubject上,因为PublishSubject可以发送onNext改变序列的值,这样在控制器ViewController里面订阅就能接收到当前view发送的序列,因为subItem是fileprivate的,所以保证了在ViewController里面不能发送onNext,当前View1对外公布的是obItem,可以被订阅
}
}
再看控制器里面的订阅
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var view1: View1!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view1.obItem.subscribe(onNext: { [unowned self] value in
print(Self.self,"订阅到值=",value)
})
.disposed(by: disposeBag)
}
看下运行结果