Jeśli tak, czy są jakieś kluczowe różnice, które nie byłyby obecne podczas korzystania z obserwacji klucz-wartość w Objective-C?
swift
key-value-observing
kodeperson
źródło
źródło
.initial
. Rozwiązanie znajdziesz tutaj . Gorąco polecam zapoznać się z dokumentacją Apple . Został niedawno zaktualizowany i zawiera wiele ważnych uwag. Zobacz także inną odpowiedźOdpowiedzi:
(Edytowano w celu dodania nowych informacji): zastanów się, czy użycie frameworka Combine może pomóc Ci osiągnąć to, czego chciałeś, zamiast używania KVO
Tak i nie. KVO działa na podklasach NSObject tak jak zawsze. Nie działa dla klas, które nie są podklasami NSObject. Swift nie ma (przynajmniej obecnie) własnego natywnego systemu obserwacji.
(Zobacz komentarze, jak ujawnić inne właściwości jako ObjC, aby KVO na nich działało)
Pełny przykład można znaleźć w dokumentacji Apple .
źródło
dynamic
słowa kluczowego w dowolnej klasie Swift, aby włączyć obsługę KVO.dynamic
słowo kluczowe trafia do właściwości, którą chcesz, aby klucz-wartość był obserwowalny.dynamic
słowa kluczowego można znaleźć w sekcji Korzystanie z języka Swift with Cocoa i Objective-C w bibliotece programistów Apple .dynamic
słowa kluczowego dla wszelkich właściwości wewnątrz klasy, które chcesz, aby były zgodne z KVO (a niedynamic
słowa kluczowego na samej klasie). To zadziałało dla mnie!Możesz używać KVO w Swift, ale tylko dla
dynamic
właściwościNSObject
podklasy. Weź pod uwagę, że chciałeś obserwowaćbar
właściwośćFoo
klasy. W Swift 4 określbar
jakodynamic
właściwość w swojejNSObject
podklasie:Następnie możesz się zarejestrować, aby obserwować zmiany w
bar
nieruchomości. W Swift 4 i Swift 3.2 zostało to znacznie uproszczone, jak opisano w Korzystanie z obserwacji wartości kluczowej w języku Swift :Zauważ, że w Swift 4 mamy teraz silne wpisywanie keypaths przy użyciu znaku ukośnika odwrotnego (
\.bar
jest to keypath dlabar
właściwości obserwowanego obiektu). Ponadto, ponieważ używa on wzorca zamykania zakończenia, nie musimy ręcznie usuwać obserwatorów (gdytoken
wypadnie poza zakres, obserwator jest usuwany za nas) ani nie musimy martwić się o wywołaniesuper
implementacji, jeśli klucz nie mecz. Zamknięcie jest wywoływane tylko wtedy, gdy wywoływany jest ten konkretny obserwator. Aby uzyskać więcej informacji, zobacz wideo WWDC 2017, Co nowego w programie Foundation .Aby to zaobserwować, w Swift 3 jest to nieco bardziej skomplikowane, ale bardzo podobne do tego, co robi się w Objective-C. Mianowicie zaimplementowałbyś to,
observeValue(forKeyPath keyPath:, of object:, change:, context:)
co (a) upewnia się, że mamy do czynienia z naszym kontekstem (a nie czymś, dosuper
czego zarejestrowała się nasza instancja); a następnie (b)super
w razie potrzeby obsłuż go lub przekaż do implementacji. I pamiętaj, aby w razie potrzeby usunąć się jako obserwator. Na przykład możesz usunąć obserwatora, gdy zostanie zwolniony:W Swift 3:
Zauważ, że możesz obserwować tylko właściwości, które mogą być reprezentowane w Objective-C. W związku z tym nie można obserwować
struct
typów ogólnych, typów Swift,enum
typów Swift itp.Omówienie implementacji Swift 2 znajduje się poniżej, w mojej oryginalnej odpowiedzi.
Używanie
dynamic
słowa kluczowego w celu osiągnięcia KVO zNSObject
podklasami jest opisane w sekcji Obserwowanie wartości kluczowej rozdziału Adopting Cocoa Design Conventions w przewodniku Using Swift with Cocoa and Objective-C :[Uwaga, ta dyskusja na temat KVO została następnie usunięta z przewodnika Używanie języka Swift z kakao i celem-C , który został dostosowany do języka Swift 3, ale nadal działa tak, jak opisano na początku tej odpowiedzi.]
Warto zauważyć, że Swift ma swój własny natywny system obserwacji właściwości , ale dotyczy to klasy określającej własny kod, który zostanie wykonany po obserwacji jej własnych właściwości. Z drugiej strony KVO jest przeznaczony do rejestracji w celu obserwowania zmian pewnej właściwości dynamicznej innej klasy.
źródło
myContext
i jak obserwujesz wiele właściwości?context
wskaźnik.context
Wskaźnik jest podawany obserwatorowi, gdyobserveValueForKeyPath:ofObject:change:context:
jest wywoływany.context
Wskaźnik może być wskaźnikiem C lub odniesieniem do obiektu.context
Wskaźnik może być używany jako niepowtarzalny identyfikator do określenia obserwowanej zmiany lub do dostarczenia obserwatorowi innych danych. "options
puste, oznacza to po prostu, żechange
nie będzie zawierać starej ani nowej wartości (np. Możesz po prostu uzyskać nową wartość samodzielnie, odwołując się do samego obiektu). Jeśli po prostu podasz,.new
a nie.old
, oznacza to, żechange
będzie zawierać tylko nową wartość, ale nie będzie starą (np. Często nie przejmujesz się tym, jaka była stara wartość, a tylko przejmujesz się nową). Jeśli chceszobserveValueForKeyPath
przekazać zarówno starą, jak i nową wartość, określ[.new, .old]
. Podsumowując,options
po prostu określa, co jest zawarte wchange
słowniku.Zarówno tak, jak i nie:
Tak , możesz używać tych samych starych interfejsów API KVO w Swift do obserwowania obiektów Objective-C.
Możesz także obserwować
dynamic
właściwości obiektów Swift dziedziczących poNSObject
.Ale ... Nie, to nie jest mocno wpisane, jak można by oczekiwać, że będzie to rodzimy system obserwacji Swift.
Używanie Swift z Cocoa i Objective-C | Obserwacja kluczowych wartości
Nie , obecnie nie ma wbudowanego systemu obserwacji wartości dla dowolnych obiektów Swift.
Tak , istnieją wbudowane obserwatory właściwości , które są silnie wpisane.
Ale ... Nie , to nie są KVO, ponieważ pozwalają jedynie na obserwację własnych właściwości obiektów, nie obsługują zagnieżdżonych obserwacji („ścieżek klucza”) i trzeba je jawnie zaimplementować.
Swift Programming Language | Obserwatorzy właściwości
Tak , możesz zaimplementować jawne obserwowanie wartości, które będzie silnie wpisane i pozwoli na dodawanie wielu programów obsługi z innych obiektów, a nawet obsługuje zagnieżdżanie / „ścieżki klucza”.
Ale ... Nie, to nie będzie KVO, ponieważ będzie działać tylko dla właściwości, które zaimplementujesz jako obserwowalne.
Bibliotekę do realizacji takich obserwacji wartości znajdziesz tutaj:
Observable-Swift - KVO for Swift - Value Observing and Events
źródło
Przykład może trochę pomóc. Jeśli mam instancję
model
klasyModel
z atrybutaminame
istate
mogę obserwować te atrybuty za pomocą:Zmiany tych właściwości spowodują wywołanie:
źródło
Tak.
KVO wymaga dynamicznego wysyłania, więc wystarczy dodać
dynamic
modyfikator do metody, właściwości, indeksu lub inicjatora:dynamic var foo = 0
W
dynamic
modyfikujące zapewnia, że odniesienia do deklaracji będą wysyłane dynamicznie i dostępne za pośrednictwemobjc_msgSend
.źródło
Oprócz odpowiedzi Roba. Ta klasa musi dziedziczyć po
NSObject
, a mamy 3 sposoby wywołania zmiany właściwościUżyj
setValue(value: AnyObject?, forKey key: String)
zNSKeyValueCoding
Użyj
willChangeValueForKey
ididChangeValueForKey
odNSKeyValueObserving
Użyj
dynamic
. Zobacz Zgodność typów SwiftA metoda pobierająca i ustawiająca właściwości jest wywoływana, gdy jest używana. Możesz zweryfikować podczas współpracy z KVO. To jest przykład obliczonej właściwości
źródło
Przegląd
Jest to możliwe
Combine
bez użyciaNSObject
lubObjective-C
Dostępność:
iOS 13.0+
,macOS 10.15+
,tvOS 13.0+
,watchOS 6.0+
,Mac Catalyst 13.0+
,Xcode 11.0+
Uwaga: Musi być używany tylko z klasami, które nie mają typów wartości.
Kod:
Szybka wersja: 5.1.2
Wynik:
Odnosić się:
źródło
Obecnie Swift nie obsługuje żadnego wbudowanego mechanizmu obserwacji zmian właściwości obiektów innych niż „self”, więc nie, nie obsługuje KVO.
Jednak KVO jest tak podstawową częścią Objective-C i Cocoa, że wydaje się całkiem prawdopodobne, że zostanie dodana w przyszłości. Obecna dokumentacja wydaje się sugerować, że:
Używanie Swift z Cocoa i Objective-C
źródło
Jedną ważną rzeczą, o której warto wspomnieć, jest to, że po aktualizacji Xcode do wersji 7 beta może pojawić się następujący komunikat: „Metoda nie zastępuje żadnej metody ze swojej nadklasy” . Dzieje się tak z powodu opcjonalności argumentów. Upewnij się, że program obsługi obserwacji wygląda dokładnie tak:
źródło
Może to być pomocne dla kilku osób -
Użyłem KVO w ten sposób w Swift 3. Możesz użyć tego kodu z kilkoma zmianami.
źródło
Inny przykład dla każdego, kto ma problem z typami takimi jak Int? i CGFloat ?. Po prostu ustawiasz swoją klasę jako podklasę NSObject i deklarujesz swoje zmienne w następujący sposób, np .:
źródło