Why Swift Disallows Weak Reference for Non-Optional Type

Why Swift disallows weak reference for non-optional type?

The very definition of a weak variable is that the variable does not increase the reference count of the object and, more importantly for your question, the variable's value will automatically be set to nil when the referenced object gets deallocated.

Since the variable must allow for a nil value, it must be optional. This is why non-optional weak variables are disallowed.

Do not declare viewController to be implicitly unwrapped (using !). Make it a proper optional (using ?).

Why do I have to unwrap a weak self?

self is inside a completion handler so it might not be there anymore once the callback gets fired (it might be a network operation or something that take some take and won't return a result for several seconds if not more).

You could check if self exists before accessing it instead of unwrapping:

VerifyObject.checkPause(withID: "abcde", 
runOnPause: {[weak self] (objectID) in
guard let self = self else { return }
self.doSomething()
})

Or even shorter only doSomething if self is not nil:

VerifyObject.checkPause(withID: "abcde", 
runOnPause: {[weak self] (objectID) in
self?.doSomething()
})

Or if you're absolutely sure that self will exist:

VerifyObject.checkPause(withID: "abcde", 
runOnPause: {(objectID) in
self.doSomething()
})

Just be mindful that this last one might cause reain cicles in case where the 2 objects have a strong reference to each other and they will never get deallocated.

weak reference instantiated in another class returns nil in Swift

It has nothing to do with "another class". An instance not retained by anything else, when assigned to a weak reference, will vanish - sooner or later. It's just that in your first code, it happens later (than when you test it).

In your second code, you test after presenter has become nil, so you actually see it.

In your first code, you don't see it, because it happens right after the print statement:

    let presenterInst = Presenter()
presenter = presenterInst
print (presenter) // it still _looks_ okay...
// but _now_ code ends — and `presenter` is now nil!

To prove this to yourself, allow some time to elapse (using my delay utility):

    let presenterInst = Presenter()
presenter = presenterInst
delay(1) {
print (presenter) // nil
}

Swift warning: 'weak' should not be applied to a property declaration in a protocol

Simply remove the weak keyword from the protocol and declare the property as weak in the conforming type instead:

class SomeClass: PipelineElement {
weak var delegate: PipelineElementDelegate?
}

What is the difference between a weak reference and an unowned reference?

Both weak and unowned references do not create a strong hold on the referred object (a.k.a. they don't increase the retain count in order to prevent ARC from deallocating the referred object).

But why two keywords? This distinction has to do with the fact that Optional types are built-in the Swift language. Long story short about them: optional types offer memory safety (this works beautifully with Swift's constructor rules - which are strict in order to provide this benefit).

A weak reference allows the possibility of it to become nil (this happens automatically when the referenced object is deallocated), therefore the type of your property must be optional - so you, as a programmer, are obligated to check it before you use it (basically the compiler forces you, as much as it can, to write safe code).

An unowned reference presumes that it will never become nil during its lifetime. An unowned reference must be set during initialization - this means that the reference will be defined as a non-optional type that can be used safely without checks. If somehow the object being referred to is deallocated, then the app will crash when the unowned reference is used.

From the Apple docs:

Use a weak reference whenever it is valid for that reference to become
nil at some point during its lifetime. Conversely, use an unowned
reference when you know that the reference will never be nil once it
has been set during initialization.

In the docs, there are some examples that discuss retain cycles and how to break them. All these examples are extracted from the docs.

Example of the weak keyword:

class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
}

class Apartment {
let number: Int
init(number: Int) { self.number = number }
weak var tenant: Person?
}

And now, for some ASCII art (you should go see the docs - they have pretty diagrams):

Person ===(strong)==> Apartment
Person <==(weak)===== Apartment

The Person and Apartment example shows a situation where two properties, both of which are allowed to be nil, have the potential to cause a strong reference cycle. This scenario is best resolved with a weak reference. Both entities can exist without having a strict dependency upon the other.

Example of the unowned keyword:

class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}

class CreditCard {
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}

In this example, a Customer may or may not have a CreditCard, but a CreditCard will always be associated with a Customer. To represent this, the Customer class has an optional card property, but the CreditCard class has a non-optional (and unowned) customer property.

Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard

The Customer and CreditCard example shows a situation where one property that is allowed to be nil and another property that cannot be nil has the potential to cause a strong reference cycle. This scenario is best resolved with an unowned reference.

Note from Apple:

Weak references must be declared as variables, to indicate that their
value can change at runtime. A weak reference cannot be declared as a
constant.

There is also a third scenario when both properties should always have a value, and neither property should ever be nil once initialization is complete.

And there are also the classic retain cycle scenarios to avoid when working with closures.

For this, I encourage you to visit the Apple docs, or read the book.

When or should i even use the weak reference for an object of a class in swift?

You have been given some misguided information.

Weak is not about making safe calls, but avoiding strong cycles between object instances that will cause memory leaks.

Safe calls are done with optional chaining.

var manager: MyManager?

manager?.someFunction() // this will not raise error if manager is nil

manager!.someFunction() // this raise error if manager is nil

cannot use optional chaining on non-optional value of type 'Any' SWIFT

Try this

let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]

let weather = jsonResult["weather"] as! [[String : Any]]
if let description = weather[0]["description"] as? String {

print(description)
}


Related Topics



Leave a reply



Submit