2015-02-02 15 views
5

Bonjour, Chciałbym przetłumaczyć ćwiczenie obiektywu z książki Aarona na szybkie, ale nie mogę znaleźć rozwiązania. Kod Objective'c to:keyPathsForValuesAffecting z NSManagedObject

@dynamic firstName; 
@dynamic lastName; 
@dynamic department; 

+ (NSSet *)keyPathsForValuesAffectingFullName 
{ 
    return [NSSet setWithObjects:@"firstName", @"lastName", nil]; 
} 

- (NSString *)fullName 
{ 
    NSString *first = [self firstName]; 
    NSString *last = [self lastName]; 
    if (!first) 
     return last; 
    if (!last) 
     return first; 
    return [NSString stringWithFormat:@"%@ %@", first, last]; 
} 

Znalazłem funkcję w dokumentacji dla programistów, ale nie mogę zrozumieć, jak zaimplementować ten kod.

być bardziej wyraźne, to doc Jabłko

do jednego Relationships

Aby automatycznie wyzwalać powiadomienia dla relacji do jednego należy albo nadpisać keyPathsForValuesAffectingValueForKey: albo wdrożyć odpowiednie metoda zgodna ze wzorcem, który definiuje do rejestrowania zależnych kluczy.

Na przykład pełne imię i nazwisko osoby jest zależne od imienia i nazwiska. Metoda, która zwraca pełną nazwę można zapisać następująco:

- (NSString *)fullName { 
    return [NSString stringWithFormat:@"%@ %@",firstName, lastName]; 
} 

Aplikacja obserwując własności fullname musi być powiadomiony, gdy albo firstName lub właściwości lastName zmienić, jak wpływają one na wartość nieruchomości.

Jednym z rozwiązań jest zastąpienie keyPathsForValuesAffectingValueForKey: określenie, że właściwość fullName danej osoby jest zależna od właściwości lastName i firstName. Listing 1 pokazuje przykład wdrożenie takiego uzależnienia:

Zamieszczone 1 Przykład wdrożenia keyPathsForValuesAffectingValueForKey:

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { 

    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; 

    if ([key isEqualToString:@"fullName"]) { 
     NSArray *affectingKeys = @[@"lastName", @"firstName"]; 
     keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys]; 
    } 
    return keyPaths; 
} 

class func keyPathsForValuesAffectingValueForKey(_ key: String) -> NSSet 

Czy ktoś mógłby mi powiedzieć, jak wdrożyć tę funkcję w systemie SWIFT?

Dziękuję za pomoc.

Odpowiedz

5

Znalazłem rozwiązanie mojego problemu! Wystarczy zastąpić keyPathsForValuesAffectingValueForKey funkcjono (klucz: String) z klasy przed

tutaj kod:

class Locataires: NSManagedObject { 
@NSManaged var firstName: String 
@NSManaged var lastName: String 
var fullName: NSString { 
    get { 
return firstName + lastName 
    } 
} 

override class func keyPathsForValuesAffectingValueForKey(key: String) -> NSSet { 
    if key == «fullName « { 
     let mesClefs = ["firstName", "lastName"] 
     return NSSet(array: mesClefs) 
    } 
    else { 
     return super.keyPathsForValuesAffectingValueForKey(key) 
    } 
} 

Dzięki za pomoc Jan

+2

Należy zauważyć, że dla Swift 2.x sygnatura funkcji klasy musi być 'override class func keyPathsForValuesAffectingValueForKey (key: String) -> Set ' –

0

Jeśli chcesz tylko sprawdzić, gdy nazwy lub dział jest aktualizowana, wystarczy użyć Swift dynamic słowa kluczowego tak:

dynamic var firstName: String 

Następnie można śledzić dokumentacji Apple na przyjęcie klucz-wartość obserwacji w Swift, wykonując Adopting Cocoa Design Patterns Guide

Podsumowanie:

  1. Dodaj słowa kluczowego dynamic do każdej właściwości, która ma obserwować.
  2. Utwórz globalną zmienną kontekstową zgodnie z dokumentacją firmy Apple.
  3. Zastąp metodę observeValueForKeyPath.
+0

Ale kiedy zmienisz 'firstName' lub' lastName', 'fullName' nie jest powiadamiany o tych zmianach, dlatego muszę wdrożyć' keyPathsForValuesAffectingValueForKey ("fullName") ', no? –

+0

Cóż, w takim przypadku możesz skorzystać z obserwatorów nieruchomości Swift. Na przykład, możesz mieć didSet i willSet obserwatorów dla swojego fullName i powiadomi cię, gdy właściwość zostanie ustawiona. – akshay

+0

Och, zapomniałem powiedzieć, że 'fullName'jest tylko do odczytu var (tylko GET), tylko' lastName' i 'firstName' change i 'fullName' nie jest powiadamiany o tych zmianach. –

2

Dla Swift 2 rozwiązania jest:

dynamic var firstName: String = "" 
dynamic var lastName: String = "" 
dynamic var fullName: String { 
    return "\(firstName) \(lastName)" 
} 

class func keyPathsForValuesAffectingFullName() -> Set<String> { 
    return Set(["firstName", "lastName"]) 
} 
1

To rozwiązanie działa dla XCode 9+, a Swift 4.0 (wersja 4.0.2 Jabłko Swift (swiftlang-900.0.69.2 dzyń-900.0.38):

@objc public class MyKVOClass : NSObject 
{ 
    // MARK: Properties 

    @objc dynamic var myKVOSubclass : KVOSubclass? 
    @objc dynamic var myKVOProperty : String? 

    @objc dynamic var myComputedKVOProperty : String? { 
     guard let mySubclassPropertyValue = self.myKVOSubclass?.mySubclassProperty, 
      let myKVOPropertyValue = self.myKVOProperty else { return nil } 

     let myComputedKVOPropertyValue = NSString(format:"%@ %@",mySubclassPropertyValue, myKVOPropertyValue) 
     return myComputedKVOPropertyValue as String 
    } 

    // MARK: Initialization 

    @objc public required override init() { 
     super.init() 
    } 

    // MARK: KVO 

    public override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> 
    { 
    if key == "myComputedKVOProperty" { 
     return Set(["myKVOSubclass", 
     "myKVOSubclass.mySubclassProperty", 
     "myKVOProperty"]) 
    } 
    // NOTE : Add more keys with the name of the property if needed... 

    return Set([]) 
    } 

} 
0

Dziękuję Darkwonder. Działa w Swift 4 !!!

Przed - Dodawanie didSet wszystkich właściwości zależnych:

class MyViewController: NSViewController { 

    // bound to a Value of NSTextField with NumberFormatter 
    @objc dynamic var amountOfBetOnRed: Int = 0 { 
    didSet { 
     updatebetButtonEnabled() 
    } 
    } 

    // same above 
    @objc dynamic var amountOfBetOnBlack: Int = 0 { 
    didSet { 
     updatebetButtonEnabled() 
    } 
    } 

    // bound to a Enabled of NSButton 
    @objc dynamic var betButtonEnabled: Bool = false 

    func updatebetButtonEnabled() { 
    betButtonEnabled = amountOfBetOnRed != 0 || amountOfBetOnBlack != 0 
    } 

} 

Po - Wymiana didSet (S) właściwości obliczana:

class MyViewController: NSViewController { 

    @objc dynamic var amountOfBetOnRed: Int = 0 

    @objc dynamic var amountOfBetOnBlack: Int = 0 

    @objc dynamic var betButtonEnabled: Bool { 
    get { 
     return amountOfBetOnRed != 0 || amountOfBetOnBlack != 0 
    } 
    } 

    override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> { 
    print("Debug: called for:", key) 

    switch key { 
    case "betButtonEnabled" : 
     return Set(["amountOfBetOnRed", "amountOfBetOnBlack"]) 
    default : 
     return super.keyPathsForValuesAffectingValue(forKey: key) 
    } 
    } 

} 

get { } mogą być pominięte, tak opuścić return ..., ale użyłem tutaj get, aby zaznaczyć, że jest to wyliczona właściwość.

Potwierdzono przy pomocy Xcode 9.0 z kodem pseudo podobnym do powyższego.

Dodany:

Czego nauczyłem się do tej pory: Funkcja keyPathsForValuesAffectingValue nazywa się kilka razy z każdej nazwy własności określonej jako @objc dynamic jeden po drugim po powrocie z init(). Ta implementacja pozwala nam określić, jakie właściwości zależą od właściwości. W rzeczywistości, addObserver jest automatycznie wywoływany w imieniu nas za kulisami. Ta funkcja nie jest wywoływana dla innych właściwości porządkowych, takich jak tylko var bez @objc dynamic.

Powiązane problemy