KVO within Swift Extension - ios

How would I go about getting my extension to observe a property on the class it's extending while also being able to remove it at a later time?
For example:
I have a UIView, and I'd like to listen for frame changes within my UIView extension. When these changes occur I need to run some code that alters the views appearance based on the new frame.
The problem I'm having is, that while I can set up an observer, I can't figure out a way to remove it. There's no deinit() and I'd like the observer to hang around for the lifecycle of the UIView.
I'd rather not have to put this removal responsibility on the developer, and I don't want to subclass.
It doesn't even have to be KVO, if there's a better way I'd love to know about it.

The usual solution to this is to use an associated object as a deallocation spy. Associated objects are released when their attached object is deallocated, so you can run code in their deinit that you want to fire when the attached object goes away. That said, doing this really well in a multi-threaded world is a little tricky to say the least. I don't recommend building your own. Instead, I suggest PMKVObserver which will handle this for you. Even if you do choose to build your own, you should study how PMKVObserver does its magic so you're not overly naïve in your implementation.
Doing this sloppily (not worrying about multi-threaded race conditions) is not too hard in Swift, but to do it really well is better done in ObjC and bridged to Swift. Again, consult the code for the tricky corner cases.

While
Extensions can add new convenience initializers to a class, but they
cannot add new designated initializers or deinitializers to a class.
Designated initializers and deinitializers must always be provided by
the original class implementation.
So I think you cannot handle it in any nice way without subclassing.

Related

I need some clarification about whether I should (could?) deallocate view-related UI elements or not

So I do understand, that I should release the objects that I own. (alloc/copy/retain stuff)
And I also do understand(kinda?), that if I had #property with retain in some of my class, or some instance variable with alloc/init, then I should write a custom dealloc to make sure those ones gets deallocated with that class.
What I do not understand is should I manually release the cell objects for example? (since I am creating it in cellForRowAtIndexPath with alloc/init? Yea, I know, that tableView should kill those cells when it gets deallocated, but do I want to make sure?
Also, could I manually release UILabel, UITextField and so on? I do know that those are gets killed when you deallocate the view, but again, still, do I want to make sure?
UPDATE:
Yea, thanks for the tip about reference counting, but the project exact purpose is to do some simple stuff, using manual memory management.
It is funny how most of the tutors nowadays skips this part entirely so the novice like myself have to figure all that stuff by themselves.
Objective C supports Automatic Reference Counting which does almost all memory management for you. I suggest you migrate your old code to ARC; this is quite easy (Xcode has refactoring support for this) and it will save you a lot of hassle.
Unless you have a strong/retain pointer to a UI element they will be automatically dealloced once they go out of the screen.
Regarding the cells - you should never dealloc them because they're intended to be reused. If you dealloc and re-init them you'll get a REALLY bad performance while scrolling.
Also, as Glorfindel said, consider using ARC (if you're not using already) and your life will be much easier.

Massive Parent-Child and delegate pattern

I'm facing with a complex design problem. Due to a hard designed graphic I can't use Apple navigation pattern as UINavigationController or other ones.
This is the app diagram
Black arrow: protocols direction
Blue arrow: parent-child pattern direction
I created this flow because I want to maintain the code inside the single ViewController clear and isolated: I thought about them as modules that they can be used somewhere in other apps.
The RootViewController is the MainVCs position manager. It decides which is the current view-controller that it must be showed and it configures it based on its status (modified by delegate methods).
The single MainVC doesn't know that RootVC exists and it call Root using protocols. The single ChildViewController doesn't know that its MainVC exists and it call the Main using protocols and so on.
Code is clear and much easy to understand, my purpose, but when I have to apply a modify to the skeleton (RootVC) from the ChildViewControllerN, child of the umpteenth ChildViewController, child of the umpteenth MainViewController, I have to propagate the protocol until the RootViewController.
My first question is: is this pattern correct? What do you think about it?
My second question is: is there a limit point where I haven't to use delegate pattern but something like KVO?
ADDING
I read a university lecture about the composite pattern that it says:
A composite object knows its contained components, that is, its children. Should components maintain a reference to their parent component?
Depends on application, but having these references supports the Chain of Responsibility pattern
So, according to the Chain, I can maintain a reference of the parent but I have to declare a custom interface for this kind of reference. However, doing this I will decrease the number of protocols, but the second question still be unanswered
Opinion:
When I go beyond a single level of parent/child relationships, I tend to stop using delegates and move to NSNotification. Frequently, I go directly to NSNotification to reduce dependencies. I prefer that to KVO because it is explicit, whereas KVO is harder to debug as the project progresses.
(Example: what looks like a simple variable assignment on a background thread results in a hard-to-diagnose crash if a listener is deallocated on the main thread between the moment of assignment and the KVO delivery.)

IOS Objective C Grandparent as delegate

I have a "GrandParentViewController" that has all methods of my application. I have a subview "ParentViewController" that contains a few subviews "ChildVC" for which I want the methods to be delegated to the "GrandParentViewController". I currently have a delegate chain from the childVC >> parentVC >> GrandparentVC but it feels wrong. What is the IOS way of doing this?
It seems that single responsibility principle is violated in your code. Maybe it is a good idea to split GrandParentViewController to several classes?
Also make sure you know what is protocol in Objective-C and how it should be used.
I do not recommend to use NSNotifications since it is good and was designed for other cases then direct delegation.
I wouldn't say that there's a set iOS way. I do something similar to what you described because it's the natural way that my VCs should be related. Go with whatever paradigm helps you keep your code clean for future changes, modularized for reusability, and of course, functional.
I will say that if any communications between VCs don't fit with your paradigm, don't force it. Use NSNotifications instead.

A way to monitor any UIView load

Actually this is a simple question with maybe not an answer for a central solution.
I would like a way to monitor in a central way every UIView start-finish loading to get metrics of the application.
I can see that viewWillLoad doesn't exist anyway in the UIViewController class and viewWillAppear is not something that it could serve the purpose.
Is this feasible in any way? I'm thinking of searching every UIView inherited class in the application and inject code somehow, but as I said I will need two methods.
Or maybe inject code to a protocol that already exists in the UIView class?
Any thoughts?
Regards.
If you are only concerned with the loading of the root view of every view controller. You could swizzle -loadView and -viewDidLoad of UIViewController. You could exchange those with methods that add start and end times to a table for each instance that calls them. Keep in mind though, that just the act of measuring it, you are going to slow down the loading.
If you want to track the loading of every view, you could swizzle -initWithFrame on UIView in the same way. In your version of the method you would start tracking before you call the real version and stop tracking once the real method has exited. However, if you have custom views that have their own initializers you will have to come up with a more complex version of that. However I do not recommend doing this. The time it takes to initialize a view is probably less time or at least very close to the amount of time it will take to track it making the timings worthless.

how to detect interface changes on iOS application

Is there any possible way to detect every change on User Interface during runtime??
I'm trying to find all objects in the current app interface.
I'm trying to to get all nodes inspecting recursively the main Window, but, for example, how to know if the top viewcontroller changes or if it's added a uiview dynamically, or is presented a modalview??
The main objective is to have a library to do this..
Any idea, help?
Thanks!
You could write your own library based on this, using advanced Objective-C techniques. I do not recommend you to do this, since it mostly breaks MVC patterns on iOS. Depends on what do you want to use it for, maybe analytics?
So these are the options I believe, if you want to actively inspect UIView hierarchy. All options are pretty complicated though.
Swizzle methods such as addSubview and removeFromSuperview of UIView, so you could know when changes like that happens. Including the getters of frame and bounds, if you wish to know the position.
You could use KVO to watch properties such as: subviews, frame, bounds, superview to notice any changes. But at one point you would have to add the same object as the observer (could be singleton).
Decide for an interval that is fired by a NSTimer and go through the hierarchy recursively beginning at keyWindow on UIApplication. This would have a big performance impact though.
There may be other options, but these are the ones I believe to be the best choices.

Resources