스위프트에서 초기화 중에 didSet을 호출할 수 있습니까?
질문.
애플의 문서는 다음과 같이 명시하고 있습니다.
willSet 및 didSet 관찰자는 속성을 처음 초기화할 때 호출되지 않습니다.속성 값이 초기화 컨텍스트를 벗어나 설정된 경우에만 호출됩니다.
초기화 중에 강제로 호출할 수 있습니까?
왜요?
제가 이 수업을 한다고 치자.
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
메소드를 만들었습니다.doStuff
통화 처리를 보다 간결하게 하기 위해, 하지만 나는 차라리 내의 속성을 처리하고 싶습니다.didSet
기능.초기화 중에 강제로 호출할 수 있는 방법이 있습니까?
갱신하다
나는 단지 우리반의 intializer의 편의성을 제거하고 초기화 후에 당신에게 속성을 설정하도록 강요하기로 결정했습니다.이것은 제가 알 수 있게 해줍니다.didSet
항상 호출됩니다.이게 전체적으로 더 좋은지는 결정하지 못했지만, 제 상황에 잘 맞습니다.
사용하는 경우defer
선택적 속성을 업데이트하거나 이미 초기화한 비선택적 속성을 추가로 업데이트하기 위해 이니셜라이저 내부에서super.init()
메소드, 그리고 당신의willSet
,didSet
등이 호출됩니다.저는 이것이 적절한 장소에서 통화를 추적해야 하는 별도의 방법을 구현하는 것보다 더 편리하다고 생각합니다.
예:
public class MyNewType: NSObject {
public var myRequiredField:Int
public var myOptionalField:Float? {
willSet {
if let newValue = newValue {
print("I'm going to change to \(newValue)")
}
}
didSet {
if let myOptionalField = self.myOptionalField {
print("Now I'm \(myOptionalField)")
}
}
}
override public init() {
self.myRequiredField = 1
super.init()
// Non-defered
self.myOptionalField = 6.28
// Defered
defer {
self.myOptionalField = 3.14
}
}
}
산출량:
I'm going to change to 3.14
Now I'm 3.14
고유한 set-Method를 만들고 init-Method 내에서 사용합니다.
class SomeClass {
var someProperty: AnyObject! {
didSet {
//do some Stuff
}
}
init(someProperty: AnyObject) {
setSomeProperty(someProperty)
}
func setSomeProperty(newValue:AnyObject) {
self.someProperty = newValue
}
}
선언함으로써
someProperty
유형:AnyObject!
(암묵적으로 포장되지 않은 선택사항), 사용자는 사용자 자신이 사용하지 않고 완전히 초기화할 수 있도록 허용합니다.someProperty
설정되어 있는전화할 때setSomeProperty(someProperty)
당신은 그것과 동등한 것을 부르고 있습니다.self.setSomeProperty(someProperty)
일반적으로 셀프가 완전히 초기화되지 않았기 때문에 이 작업을 수행할 수 없습니다.부터someProperty
초기화할 필요가 없으며 사용자가 자신에 의존하는 메서드를 호출하는 경우 Swift가 초기화 컨텍스트를 떠나 didSet이 실행됩니다.
올리버의 대답의 변형으로, 당신은 그 선들을 폐쇄로 포장할 수 있습니다.예:
class Classy {
var foo: Int! { didSet { doStuff() } }
init( foo: Int ) {
// closure invokes didSet
({ self.foo = foo })()
}
}
편집: 브라이언 웨스트팔의 대답은 더 친절합니다.그의 좋은 점은 그것이 의도를 암시한다는 것입니다.
저도 같은 문제가 있었고 이것은 저에게 효과가 있습니다.
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
defer { self.someProperty = someProperty }
}
func doStuff() {
// do stuff now that someProperty is set
}
}
하위 클래스에서 이 작업을 수행하면 작동합니다.
class Base {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
required init() {
someProperty = "hello"
}
func doStuff() {
print(someProperty)
}
}
class SomeClass: Base {
required init() {
super.init()
someProperty = "hello"
}
}
let a = Base()
let b = SomeClass()
인a
예,didSet
트리거되지 않습니다.하지만b
예,didSet
하위 클래스에 있기 때문에 트리거됩니다.그것은 무엇과 관련이 있습니다.initialization context
로, 이 에는 말로경, 는에우이정을합니다.superclass
그것에 대해 신경을 썼습니다.
이것이 해결책은 아니지만, 클래스 생성자를 사용하는 것이 대안이 될 수 있습니다.
class SomeClass {
var someProperty: AnyObject {
didSet {
// do stuff
}
}
class func createInstance(someProperty: AnyObject) -> SomeClass {
let instance = SomeClass()
instance.someProperty = someProperty
return instance
}
}
호출하려는 특정한 경우willSet
또는didSet
東京의 init
슈퍼 클래스에서 사용할 수 있는 속성의 경우 슈퍼 속성을 직접 할당하기만 하면 됩니다.
override init(frame: CGRect) {
super.init(frame: frame)
// this will call `willSet` and `didSet`
someProperty = super.someProperty
}
이러한 경우에는 폐쇄가 있는 샤를리즘 솔루션도 항상 작동합니다.그래서 저의 해결책은 그저 대안일 뿐입니다.
유감스럽게도 루트 클래스가 초기화될 때 세트 관찰자가 호출되지 않았습니다.
클래스가 하위 클래스가 아닌 경우, 원하는 기능을 달성하기 위해 게터와 세터를 사용해야 합니다.
class SomeClass {
private var _test: Int = 0
var test: Int {
get { _test }
set { _test = newValue }
}
init(test: Int) { self.test = test }
}
또는 클래스가 하위 클래스인 경우 didSet을 사용하여 다음 작업을 수행할 수 있습니다.
override init(test: int) {
super.init()
self.test = test
}
super.init()가 호출된 후에 didSet이 호출되어야 합니다.
시도하지 않았지만 효과가 있을 수도 있는 한 가지:
init(test: int) {
defer { self.test = test }
}
참고: 속성을 사용할 수 없도록 설정하거나 속성의 기본값을 설정하거나 클래스 속성의 래핑을 해제해야 합니다.
obj-discovery 방식으로 해결할 수 있습니다.
class SomeClass {
private var _someProperty: AnyObject!
var someProperty: AnyObject{
get{
return _someProperty
}
set{
_someProperty = newValue
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
언급URL : https://stackoverflow.com/questions/25230780/is-it-possible-to-allow-didset-to-be-called-during-initialization-in-swift
'programing' 카테고리의 다른 글
SQL: 타임스탬프 날짜에서 1일 빼기 (0) | 2023.05.03 |
---|---|
몽구스에서 "LIKE" 연산자를 사용하려면 어떻게 해야 합니까? (0) | 2023.05.03 |
셸 명령이 실행될 때 에코하는 방법 (0) | 2023.04.28 |
모든 시트 내용을 지우는 가장 빠른 방법 VBA (0) | 2023.04.28 |
authenticationScheme이 지정되지 않았으며 기본 인증 및 사용자 지정 권한 부여로 DefaultChallengeScheme을 찾을 수 없습니다. (0) | 2023.04.28 |