iOS Swift 中的变量侦听器
Variable listener in iOS Swift
我正在尝试制作一个独立的 class/library,它 运行 可以自行处理内部错误,但也会向前端提供反馈(状态)以进行可能的用户交互。在 Android 中,我将使用 Listener 解决此问题:
class Status(errCode:Int=0, msg:String=""){
var errCode:Int=0
var text:String=""
private var listener: ChangeListener? = null
init {
this.errCode=errCode
this.text=msg
}
fun set(errCode:Int, msg:String) {
this.errCode=errCode
this.text=msg
if (listener != null) listener!!.onChange()
}
fun getListener(): ChangeListener? {
return listener
}
fun setListener(listener: ChangeListener?) {
this.listener = listener
}
interface ChangeListener {
fun onChange()
}
}
每当我想更新它时,例如在异常情况下,我调用:
catch (e: IOException) {
this.status.set(109,"someException: $e")
}
在 MainActivity 中,我只需要处理这些更改:
myObj.status.setListener(object : Status.ChangeListener {
override fun onChange() {
when(myObj!!.status.errCode) {
//errors
109 -> log(myObj!!.status.text) //some Exception
111 -> myObj!!.restart() //another exc
112 -> myObj!!.checkAll() //some other error
...
在Swift中我发现didSet看起来很相似。我读到你可以将它附加到一个结构上,这样每当结构中的某些内容发生变化时,它就会被调用。所以我将我的“struct Status”添加到我的“struct myObj”中,如下所示:
struct myObj {
var status:Status=Status(errCode: 0, msg: "Init")
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode=err
msg=txt
}
}
并且在我的代码中我初始化了一个新的 myObj 实例
var mObj:myObj=myObj.init() {
didSet{
switch myObj.status.errCode{
case 1:
promptOkay()
case 113:
obj.errorHandling()
default:
log(txt: mObj.status.msg)
}
}
}
然而,它永远不会触发 didSet,即使内部函数应该改变 Status。我读到 didSet 没有在 init 上触发,但是在初始化应该 运行 完全独立的 class 对象后,我现在没有 运行 任何东西。我想先验证一下这个方法是否可行,然后再进一步,然后再解开所有的问题。
didSet
必须在 属性 上声明,而不是在初始化期间声明:
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
// status did change
print("new error code: \(status.errCode)")
}
}
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode = err
msg = txt
}
}
}
let obj = MyObj()
obj.status.set(err: 10, txt: "error 10") // prints "new error code: 10"
此时您可以对 didSetClosure
中对 obj.status
所做的每个更改做出反应。
编辑 — 从 class
外部对 didSet 做出反应
如果您想响应来自 MyObj
外部的更改,我建议您使用闭包:
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
statusDidChange?(status)
}
}
// closure to call when status changed
var statusDidChange: ((Status) -> Void)? = nil
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode = err
msg = txt
}
}
}
这样,您可以从外部分配一个闭包来执行自定义操作:
let obj = MyObj()
obj.statusDidChange = { status in
// status did change
print("new error code: \(status.errCode)")
}
obj.status.set(err: 10, txt: "error 10") // prints "new error code: 10"
编辑 2 — 直接从初始化调用 didSet 闭包
您也可以在初始化期间手动调用 statusDidChange
闭包。
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
statusDidChange(status)
}
}
// closure to call when status changed
var statusDidChange: (Status) -> Void
init(status: Status, statusDidChange: @escaping (Status) -> Void) {
self.status = status
self.statusDidChange = statusDidChange
self.statusDidChange(status)
}
}
let obj = MyObj(status: MyObj.Status(errCode: 9, msg: "error 09")) { status in
// status did change
print("new error code: \(status.errCode)")
}
obj.status.set(err: 10, txt: "error 10")
这将打印
new error code: 9
new error code: 10
我正在尝试制作一个独立的 class/library,它 运行 可以自行处理内部错误,但也会向前端提供反馈(状态)以进行可能的用户交互。在 Android 中,我将使用 Listener 解决此问题:
class Status(errCode:Int=0, msg:String=""){
var errCode:Int=0
var text:String=""
private var listener: ChangeListener? = null
init {
this.errCode=errCode
this.text=msg
}
fun set(errCode:Int, msg:String) {
this.errCode=errCode
this.text=msg
if (listener != null) listener!!.onChange()
}
fun getListener(): ChangeListener? {
return listener
}
fun setListener(listener: ChangeListener?) {
this.listener = listener
}
interface ChangeListener {
fun onChange()
}
}
每当我想更新它时,例如在异常情况下,我调用:
catch (e: IOException) {
this.status.set(109,"someException: $e")
}
在 MainActivity 中,我只需要处理这些更改:
myObj.status.setListener(object : Status.ChangeListener {
override fun onChange() {
when(myObj!!.status.errCode) {
//errors
109 -> log(myObj!!.status.text) //some Exception
111 -> myObj!!.restart() //another exc
112 -> myObj!!.checkAll() //some other error
...
在Swift中我发现didSet看起来很相似。我读到你可以将它附加到一个结构上,这样每当结构中的某些内容发生变化时,它就会被调用。所以我将我的“struct Status”添加到我的“struct myObj”中,如下所示:
struct myObj {
var status:Status=Status(errCode: 0, msg: "Init")
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode=err
msg=txt
}
}
并且在我的代码中我初始化了一个新的 myObj 实例
var mObj:myObj=myObj.init() {
didSet{
switch myObj.status.errCode{
case 1:
promptOkay()
case 113:
obj.errorHandling()
default:
log(txt: mObj.status.msg)
}
}
}
然而,它永远不会触发 didSet,即使内部函数应该改变 Status。我读到 didSet 没有在 init 上触发,但是在初始化应该 运行 完全独立的 class 对象后,我现在没有 运行 任何东西。我想先验证一下这个方法是否可行,然后再进一步,然后再解开所有的问题。
didSet
必须在 属性 上声明,而不是在初始化期间声明:
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
// status did change
print("new error code: \(status.errCode)")
}
}
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode = err
msg = txt
}
}
}
let obj = MyObj()
obj.status.set(err: 10, txt: "error 10") // prints "new error code: 10"
此时您可以对 didSetClosure
中对 obj.status
所做的每个更改做出反应。
编辑 — 从 class
外部对 didSet 做出反应如果您想响应来自 MyObj
外部的更改,我建议您使用闭包:
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
statusDidChange?(status)
}
}
// closure to call when status changed
var statusDidChange: ((Status) -> Void)? = nil
struct Status {
var errCode:Int
var msg:String
mutating func set(err:Int, txt:String){
errCode = err
msg = txt
}
}
}
这样,您可以从外部分配一个闭包来执行自定义操作:
let obj = MyObj()
obj.statusDidChange = { status in
// status did change
print("new error code: \(status.errCode)")
}
obj.status.set(err: 10, txt: "error 10") // prints "new error code: 10"
编辑 2 — 直接从初始化调用 didSet 闭包
您也可以在初始化期间手动调用 statusDidChange
闭包。
class MyObj {
var status: Status = Status(errCode: 0, msg: "Init") {
didSet {
statusDidChange(status)
}
}
// closure to call when status changed
var statusDidChange: (Status) -> Void
init(status: Status, statusDidChange: @escaping (Status) -> Void) {
self.status = status
self.statusDidChange = statusDidChange
self.statusDidChange(status)
}
}
let obj = MyObj(status: MyObj.Status(errCode: 9, msg: "error 09")) { status in
// status did change
print("new error code: \(status.errCode)")
}
obj.status.set(err: 10, txt: "error 10")
这将打印
new error code: 9
new error code: 10