简体   繁体   中英

How to point to objects that aren't yet instantiated

I am preloading data on an app's first launch into Core Data, need to point to objects yet to be instantiated and can't figure out how to do this. I saw a similar question, though the solution isn't applicable in this situation.

Say I have 3 classes

class Person {
  var nationOfBirth: Nation
  ...
}

class City {
  var mayor: Person
  ...
}

class Nation {
  var capitalCity: City
  ...
}

If i am loading an initial data set of nations, then cities, then people (or any other order) then no matter which order I load them in I will need to set instances yet to be instantiated (though I know they will be) and I'm struggling to figure out how to do this and will appreciate any help

One of this fields must be optional, because in your example you have cycle references. Also Optional field in this case must have week reference for another field to clear memory correctly in the end. Your code:

class Person {
    var nationOfBirth: Nation
    init(nation: Nation) {
        nationOfBirth = nation
    }
}

class City {
    var mayor: Person
    init(person: Person) {
        mayor = person
    }
}

class Nation {
    weak var capitalCity: City?
}

//initialization
let nation = Nation()
let person = Person(nation: nation)
let city = City(person: person)
nation.capitalCity = city

In swift if you are declaring field in class without default initialisation you must initialise it in constructor(init). In your case you have 3 classes, each with one field of another class without default initialisation. So you need to initialise then in init method.

To initialise Person you need object of Nation, to initialise Nation you need object of City, to initialise City you need object of Nation, and again you need object of Person, than City, than Nation. As you you see it is infinity loop.

To solve this problem you need to break this loop. You can do it only with setting field of One class as optional (with ? in the end of type). After that you don't need to initialise that field in initialiser, because now it can contain nil(nothing).

If you don't need to initialise it in initialiser, you can now create member of class with optional field without object of another class and just set it in the end. In my code you can see, that City field in Nation is set as optional, so i can create member of Nation without initial City value( let nation = Nation() ).

After that, as i have member of class Nation, i can create Person with initialiser that takes Nation object(let person = Person(nation: nation)).

In the same way as now we have created member of person we can create member of city( let city = City(person: person) ).

In the end we have member of city, so we can set it to nation object, that was created at the beginning without city( nation.capitalCity = city ).

About why we need weak reference in this case you can read hear - https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_92

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM