Precondition Swift 3 - ios

I am following the last conference of Apple about the GCD on this link:https://developer.apple.com/videos/play/wwdc2016-720/?time=33
I got to the point where it speaks of the precondition here: https://developer.apple.com/videos/play/wwdc2016-720/?time=1267, a new feature in Swift 3.
Arrived at this point: https://developer.apple.com/videos/play/wwdc2016-720/?time=1474 is used this:
.register(observer:, queue:)
my question: how this function retains object BusyController?
https://developer.apple.com/videos/play/wwdc2016/720/?time=1550

You ask how this register(observer:queue:) retains BusyController.
First, let's step back: Let's not get lost in the details of his example. He's not saying that it will establish a strong reference, merely that it could, and therefore you should be cautious about just trying to clean up in deinit.
So, how could DataTransform retain BusyController? It simply could maintain a strong reference to its observer. Note, do not conflate this custom register method example with the standard observer methods: They're just saying "imagine that the DataTransform object established a strong reference to BusyController..."
But, as he goes on to say "but you're skilled developers, and you know how to fix this problem; use a weak reference." So, generally, we wouldn't write observation methods that maintained strong references to their observers.
But, as he goes on to say, even if you're good about avoiding strong reference cycles, the object graph can get pretty complicated, so it's not always a good idea to rely upon deinit to clean up. He's advocating for an explicit invalidate process, and possibly using preconditions to test that the object has been invalidated by the time deinit is called.

Related

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

As far as i know the weak reference of swift is used because if the object gets nil and you call a method from it, it won't crash your application and just gets ignored. But isn't it a bad practice to allow some of your code to call a function on a not existing object of a class? Wouldn't it be cleaner to just avoid this scenario with good code?
Example what i mean:
weak var manager: MyManager?
manager.someFunction()
Now if the manger object is nil it just won't get called. I know it has it's easy to write code like this but is it really the best practice?
Sorry if this questions was asked before, but i only found explanations of weak and strong. I ask this because a friend of mine told me to use the weak reference to avoid an error call and i think that this is not the best way to handle nil objects because it seems like dirty code to me.
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
The main point is that using weak communicates something about ownership. It's also frequently used to prevent retain cycles.
That it nils out automatically is useful for some patterns like observing.
Calling methods on nil is a somewhat different topic, which often comes convenient and allows for cleaner (less cluttered, easier to read) code.
For doing more complex logic, you often assign the weak variable into a strong one, so that you can be sure that the whole code runs as you expect it to, and not suddenly works with nil in half the code.

Im confused on how can I manipulate the properties inside an instance when it gets deinitialized?

I have this from either the Apple documentation or the swift book
When an instance gets deinitialized, you still have access to the
properties inside the instance and can manipulate them as needed
before the instance totally goes away.
I'm confused, do they mean when we for example do some mathematical action using the instances property in the deinit() method? or lets say when we print a property of type string that was part of a specific instance, also from the deinit() method?
If so, then is the deinit() method the only way to manipulate a property when it is being deinitialized?
if you have a swift class with a a var you know you have to clean up after because ARC can't free it (e.g. C memory), you can still do that in deinit. The pointers stored in the properties are still valid!
it isn't useful for much more though (ok end observing with the notification center or kvo) BECAUSE there is no guarantee WHEN deist is called. ONLY that it is called before deallocation [whenever that is]
deinit is called right before deallocation (when the retainCount reaches 0), so all your properties are still valid and you can print your string. You don't need to set properties to nil explicitly in deinit as that happens automatically.
This being said, most classes don't even need deinit implemented
Most of the time I used deinit to remove observer that the instance is registered to, post any notifications if needed, and things like that.
As far as I know, the deinit method gets called just before the instance gets deinitialized, to give you a final opportuninty to do whatever you need to do (cleanup, close a file, terminate a network connection, etc).
What the documentation says is that, at the time deinit is called your object has not been deinitialized yet (but will be very soon), so you still can (for the last time) access its properties.

Manually set nil to swift object to avoid retain cycle?

I've been profiling one of the apps written in swift lately and been very frustrated with ARC in general, coming from languages where mark-and-sweep GC is the norm.
Especially, UIViewControllers that are very complex with lots of dependencies to other class, I've been failing to get ARC working properly. But I know that simply setting retained objects to nil gets them deallocated without dabbling with ARC.
This is especially true for UIViewController where I can set nil to all retained objects in viewDidDisappear or the similar.
Is this kind of practice considered bad / harmful? Should I just try harder to get ARC working?
edit: By not working, I mostly mean to break Strong Reference Cycle, which becomes quite unwieldy when there are multiple hierarchies of dependencies.
edit: FYI, I'm aware that using weak / unowned in declaration / capture list breaks the retain cycle. I'm asking in cases where using those norms become unwieldy due to the complexity of an object or, rather, the retain cycle of an object.
I think you should take a look at your class structure - basically work out which classes should "own" certain properties (i.e. strong reference) and who just needs to be referencing them when they are available (i.e. weak references).
I think it is well worth thinking about this, as it will probably streamline your code. It will also give you an opportunity to really think about privilege - do all these other classes really need access to these objects etc.
The real problem with setting things to nil is that you have to be sure that you are catching all strong reference cycles and that, ultimately, you are not benefiting from ARC making your life easier.
Try deinit Method its wright way I guess
deinit{
person = nil
}

Why I should access the instance variable directly from within an initialization method?

The Apple Programming with Objective-C document states that:
You should always access the instance variables directly from within
an initialization method because at the time a property is set, the
rest of the object may not yet be completely initialized. Even if you
don’t provide custom accessor methods or know of any side effects from
within your own class, a future subclass may very well override the
behavior.
But I don't know what side effects will be in a setter method, please give me a example to explain why I have to access the instance variable directly from within an initialization method
The answer is simple - it is code smell. Dot notation like self.foobar = something in Objective-C is just a syntactic sugar for messaging.
Sending messages to self is normally fine. But there are two cases you need to avoid them:
1. When the object is being created, and
2. When the object is being destroyed.
At these two times, the object is in a strange in-between state. It lacks integrity. Calling methods during these times is a code smell because every method should maintain invariants as it operates on the object.
If a setter method is overridden by a subclass, you have no guarantee that your instance variable will contain the correct data. If you want to maintain data integrity within your objects during a crucial phase such as initialization, you should do as Apple recommends.
In addition to #JacobRelkin point, side effects can include Key-Value Observing. Other objects can observe changes even during -init* and -dealloc. I've had a KVO -dealloc bug in the past.
It truly is a best practice to setup and tear down the ivars directly.

ARC in iOS questions

~ Will ARC always release an object the line after the last strong pointer is removed? Or is it undetermined and at some unspecified point in the future it will be released? Similarly, assuming that you don't change anything with your program, will ARC always be the same each time you run and compile your program?
~ How do you deal with handing an object off to other classes? For example, suppose we are creating a Cake object in a Bakery class. This process would probably take a long time and involve many different methods, so it may be reasonable for us to put the cake in a strong property. Now suppose we want to hand this cake object off to a customer. The customer would also probably want to have a strong pointer to it. Is this ok? Having two classes with strong pointers to the same object? Or should we nil out the Bakery's pointer as soon as we hand off?
Your code should be structured so the answer to this doesn't matter - if you want to use an object, keep a pointer to it, don't rely on ARC side effects to keep it around :) And these side effects might change with different compilers.
Two strong pointers is absolutely fine. ARC will only release the object when both pointers are pointing to something else (or nothing!)
ARC will implement the proper retains and releases at compile time. It will not behave any different than if you put them in there yourself so it will always do the same compilation and to answer your question should always behave the same. But that said it does not mean that your object will always be released immediately after the pointer is removed. Because you never call dealloc directly in any form of objective C you are only telling it that there is no reference count and that it is safe to release. This usually means that it will be released right away though.
If you pass an object from one class to another and the receiving class has a strong property associated with it and the class that passes it off eventually nils its pointer it will still have a reference count of at least 1 and will be fine.
Ok, first this answer might helpt you also a little bit: ARC equivalent of autorelease?
Generally after the last strong variable is nilled, the object is released immediately. If you store it in a property, you can nil the property, assign it to something like __strong Foo *temp = self.bar; before you nil, and return that local __strong variable (although arc normally detects the return, and inferes the __strong byitself).
Some more details on that: Handling Pointer-to-Pointer Ownership Issues in ARC
DeanWombourne's answer is correct; but to add to (1).
In particular, the compiler may significantly re-order statements as a part of optimization. While method calls will always occur in the order written in code (because any method call may have side effects), any atomic expression may be re-ordered by the compiler as long as that re-order doesn't impact behavior. Same thing goes for local variable re-use, etc...
Thus, the ARC compiler will guarantee that a pointer is valid for as long as it is needed, no more. But there is no guarantee when the pointed to object might be released other than that it isn't going to happen beyond the scope of declaration. There is also no guarantee that object A is released before B simply because A is declared and last used before B.
IN other words, as long as you write your code without relying on side effects and race conditions, it should all just work.
Please keep you code proper as it has diffrent behaviour on diffrent complier.

Resources