wake-up-neo.com

Xcode 10 - Instanz wird sofort freigegeben, da Eigenschaft 'schwach' ist

Ich habe kürzlich Xcode 10 heruntergeladen und bei der Verwendung von weak- oder unowned -Variablen einen offensichtlichen Fehler festgestellt. Ich habe es geschafft, ein einfaches Beispiel zu erstellen, das das Problem aufzeigt, damit die Leute es neu erstellen können.

class MainClass {
    weak var weakClass: SomeClass!

    init() {

        // WARNING: Instance will be immediately deallocated because property 'weakClass' is 'weak'

        self.weakClass = SomeClass()
    }
}

class SomeClass {}

Wie der Fehler besagt, wird die Zuordnung von weakClass sofort aufgehoben, sobald MainClass initialisiert wurde und immer null ist.

Ich habe mit Xcode 9.3 den gleichen Spielplatz geöffnet und kann bestätigen, dass der Code ohne Fehler oder Warnungen funktioniert

Ist das ein Fehler in Xcode 10 oder bekomme ich nichts. Wenn ja, gibt es Abhilfemaßnahmen?

BEARBEITEN: Ursprüngliches Beispiel

class LoginCoordinator {

    var viewModel: LoginViewModel?
    var viewController: LoginViewController?

    init() {
        viewModel = LoginViewModel()
        viewModel?.coordinator = self
        viewController = LoginViewController(viewModel: viewModel!)
    }
}


class LoginViewModel: ViewModelDelegate {
    weak var coordinator: LoginCoordinator?
}

coordinator ist in LoginViewModel immer null

AppDelegate.Swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func setupView() {
        let coordinator = LoginCoordinator()
        let navigationController = UINavigationController(rootViewController: coordinator.create)

        navigationController.isNavigationBarHidden = true
        navigationController.navigationBar.isTranslucent = false

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
        window?.layer.cornerRadius = 6
        window?.layer.masksToBounds = true
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        setupView()
        return true
    }
11
Nader Besada

Um dies zu verstehen, müssen Sie das Konzept von ARC kennen. ARC Konzept ist automatische Referenzzählung bedeutet, dass ARC etwas im Speicher behält, solange ein zugewiesener Speicher stark von einer Variablen referenziert wird. Wenn es (ARC) feststellt, dass ein zugewiesener Speicher keine starke Referenz hat, wird die Zuordnung aufgehoben. Daher wird die Warnung weakClass sofort deallocates einmal MainClass initialisiert und ist immer null. Weil es keinen starken Bezug hat. Bitte kommentieren Sie jeden Zweifel.

Ein Beispiel für die Erstellung eines Beibehaltungszyklus:

class A {
var classBObject: B?

  init() {
     classBObject = B()
     classBObject.classAObject = self // Creates a retain cycle
 }
}

class B {
   var classAObject: A? // Strong(by default all are strong) variable create retain cycle
}

Also, in class B, Wenn wir weak var classAObject Nehmen, wird der Beibehaltungszyklus nicht stattfinden.

8
vivekDas

Dies ist der Zweck von weak. Swift verwendet die Referenzanzahl zum Verwalten des Speichers. Ein starker Zeiger erhöht die Referenzanzahl des angezeigten Objekts um 1, ein schwacher Zeiger erhöht die Referenzanzahl nicht. Ein Objekt mit der Referenzanzahl 0 wird freigegeben.

Ihre Instanz von SomeClass wird nur von einem schwachen Zeiger angezeigt, sodass der Referenzzähler 0 ist. Als Ergebnis wird die Zuordnung sofort aufgehoben.

Schwach ist nützlich, um Retentionszyklen zu vermeiden. Zum Beispiel bei der Flucht vor der Schließung und beim Entwurfsmuster für die Delegierung.

4
ukim

Die Frage ist: "Wird diese Referenz an anderer Stelle stark referenziert? Wenn ja, wird die Zuordnung nicht aufgehoben."

Ich schlage vor, dass Apples Warnmeldung irreführend ist. Ich denke, dass es angeben sollte, dass es sofort freigegeben wird, wenn sein enthaltendes Objekt freigegeben wird oder wenn andere starke Verweise darauf freigegeben werden.

Hier ist der Grund.

Wir haben diese Warnung für eine Instanz in einem View-Controller und die Zuordnung der schwachen Var wird nicht sofort aufgehoben. Der View-Controller wird angezeigt, die schwache Variable wird instanziiert, wir warten, klicken auf eine Schaltfläche, die einen Haltepunkt erreicht, und yup, die schwache Variable ist immer noch nicht null. Wenn der Ansichts-Controller verschwindet und freigegeben wird, wird die schwache Variable wird sofort freigegeben.

Aber wieso? Nun, wenn der Teil des Codes kommt, der einen schwachen Verweis auf die Variable hat, hat der andere Code bereits eine Anzahl von 3, und obwohl er schwach ist, wird er can't Sofort verworfen.

Sie können dies mit po myObject.retainCount Überprüfen. Es ist nicht garantiert genau, aber es wird Ihnen eine Idee geben. Wenn der Retaincount des Objekts> 1 ist und es an einer anderen Stelle stark verknüpft ist (bitte fügen Sie einen Kommentar in Ihren Code ein, um anzugeben, wo stark auf das Objekt verwiesen wird), funktioniert schwach. Um eine Compiler-Warnung zu vermeiden, verweisen Sie nicht direkt auf das Objekt, sondern auf den starken Verweis im anderen Objekt.

Ich denke also, dass Apple diese Warnung umformulieren muss, weil sie sicherlich irreführend ist.

0
Alex Zavatone