Using viewDid/WillMoveToSuperview to setup an NSView - objective-c

I'd like to know which is the best way to setup an NSView.
The only method suitable for this purpose, seems to be viewDidMoveToSuperview.
In this method I can add subviews and inviewWillMoveToSuperview I can do geometry operation on frame etc.
But these are only my suppositions... I can't find a useful documentation that explain where is the better function to perform setup operations.
What do you think about that?

The reason you don't find any documentation on where to set up your NSViews is probably that you can set up views, add subviews, etc. in pretty much any method, as long as it is called on the main thread.
For simple apps, applicationDidFinishLaunching: of the application delegate is a useful place.
When the app grows, you might want to consider doing this lazily, when a new window is opened or when a view is added.
For normal apps, you won't need to do anything in viewWillMoveToSuperview/viewDidMoveToSuperview.

Related

Is it better to layout subviews in layout/layoutSubviews method?

This question is for both cocoa and cocoa touch. But I'll write an example just for cocoa.
As I understood, I can setNeedsLayout to YES multiple times in a cycle and -layout will be called just once. But are there any other benefits of laying out subviews in -layout method?
Explanation / example: At the moment I'm laying out my subviews in custom viewController (that has default NSView) every time I call custom redraw method. And I call redraw method only when user changes some properties so I really want to relayout subviews.
There are plenty of external circumstances not under your direct control that might cause the system to want to lay out your views. For example, device rotation or incoming calls on iOS, or window resizing on OS X. If you have your layout logic in the standard places, then your code accommodates these without any additional effort, and in the places your internal state changes, you can request such a layout explicitly.
To turn your question around: is there a significant benefit to not doing your layout in the standard way? Do you believe that this will be a performance issue? Have you measured it to see whether it is actually a performance issue?

Registering all view controllers for NSNotifications

I have a custom graphic that is to be displayed to a user when an event occurs. The graphic needs to be displayed on whichever viewController is currently being displayed to the user.
The way i have programmed it so far is by adding to ALL viewcontrtollers:
1) the .h file for the custom graphic class
2) an observer for the NSNotification event that is raised
3) the method which actually draws the graphic.
This doesnt feel like a very efficient way of doing things and i was wondering if anyone has a better way of doing things?
To me it sounds like you've done it in a fairly sane way. The only other way I can think is to just add the graphic to the window which would then overlay on the current view controller and you'd only need to have one object listening for the notification. You could use the app delegate for instance. But then you would have to worry about rotation of the screen yourself when adding the graphic over the top.
What you are doing is correct .. The only thing you can improve is to mauve the drawing graphics part to the custom graphic class.. (if you are not already doing so...
just Make a UIViewController variable as a member variable to the graphics class..and then set it up to the current view displaying..after you receive the notifications..and the class will itself draw the code based on the ViewController you set it up to
The reason it doesn't feel efficient is that you're duplicating a lot of code. That's more work at the outset, and it creates a maintenance headache. You should be taking advantage of the inheritance that's built into object oriented languages, including Objective-C.
If you want all your view controllers to share some behavior, then implement that behavior in a common superclass. Derive all your other view controllers from that superclass, and they'll all automatically get the desired behavior. Your superclass's initializer can take care of registering the view controller for the notification(s) that you care about, and -dealloc can unregister it. This way, you don't have to clutter up each view controller with the same repeated code, and if you want to change the code you only have to do it in one place.

Adding a Target for All UIGestureRecognizers

I am working to integrate a current iOS application with an analytics suite. One of analytics items that we will use in our UX analysis is a complete track of all gestures (at least ones that are recognized through a UIGestureRecognizer subclass). My goal is to add this hook into the analytics suite without having to subclass each gesture recognizer.
My initial thought was to write a category that had an override for an existing method on UIGestureRecognizer, but I couldn't find a safe way to do that (and I also learned that there is no way to call the class's existing implementation of that method without method swizzling).
My next approach would be to use poseAs and simply have a subclass of UIGestureRecognizer pose as UIGestureRecognizer and add a target on init. However, I then learned that poseAs is deprecated (and has been for a while), so I also abandoned this approach.
Obviously, I could subclass each gesture recognizer we are using, but I feel that doesn't take advantage of the dynamic nature of obj-c.
Is there a good way to accomplish this?
After research, I don't think there is a clean way to do this. I ended up subclassing all of the gesture recognizers to accomplish this shared functionality.

Making classes work together in obj-C

I'm writing a program for iPhone that will first let the user take a photo, then will dynamically retrieve a colour of the place where the user taps on the image, and draw a rectangle of that colour. I have two relevant classes for this: AppViewController and AppView. The former contains all the UI elements and IBActions, the latter the position of last tap, the touches-handling methods and the drawRect (and a static method to get colour data at a given coords of an image).
What I wanted to do is to put the touch-handling (calling drawRect in touchesMoved/Ended) and the drawRect in the AppViewController. That doesn't work, since that class doesn't inherit from UIView, but from UIViewController. What's the correct way to do that?
Another way to phrase that: How to constantly change something (well, constantly as long as the user is swiping across the screen) in a class that doesn't support touch-detection methods?
(This probably doesn't explain it well. Please ask clarifying questions).
I think the delegate pattern might be helpful to you in this situation. You could call your delegate's shouldUpdateRectangle selector in touchesMoved/Ended.
There is not really a correct way to move the view's behaviors into a view controller, since that is not the way the classes are meant to be used. You should probably look at what's driving you to try to subvert the framework's design this way, because that is likely going to be easier to fix.
It's not uncommon, though, for a view to call out to a supporting class for help in this stuff. You could certainly have your view's drawRect: call methods in the view controller, though I would be careful about mixing their concerns too much, because it could get hard to figure out who's responsible for what.

Working with many interface elements in Cocoa

My app requires an interface that has many buttons, text fields and matrixes. And they need to change from time to time. Right now I do this by having all elements in IB already and hiding/showing/moving them when needed. What would others recommend? Should I do that? Should I use an NSTabView? NSView? Should create the elements programatically? If so, what if I have an element that is already created that I need again without changes? It would be a waste of releasing it and creating it again.
Any help would be greatly appreciated.
In my opinion, it's better to create interfaces programmatically if you have to animate views around a lot. If it's just a matter of hiding/unhiding them, IB works great, but if you need re-layout or create unknown numbers of views dynamically it's not worth trying to make it all work with nib files.
As for general advice:
Create subclasses (from UIView or UIControl or one of their subclasses) for every kind of element you're going to use. It's tempting to piece together composite views from your UIViewController, but you'll really be much better off creating real classes.
Study the standard Cocoa view classes, and try to create similar API:s in your own controls and views.
Put as much data (sub-element positioning etc) into a plist, so that you can easily change it from one centralized place instead of having to dig around in the code.
If you are often creating several dozen short-lived views, it's worth keeping them in a pool and reusing them. But if it's just a few labels being added and removed intermittently I wouldn't worry too much about it. As usual: don't optimize too early.
Your current approach sounds fine. If you're showing/hiding them but otherwise they remain unchanged, why go through the trouble of creating them with code, when your XIB keeps a "freeze-dried" copy of exactly what you need already?
As long as you're keeping them within logical groups, you can just move/swap/show/hide the group's container (like NSBox or an NSView). If you have a LOT of logical groups, which aren't always shown every session, you can separate them out into their own XIBs and only load them when they're needed, to save launch time and memory.
If you use NSViewController, it's even better because you can make clean breaks for each logical group. Load the panel as the view and the view controller will keep outlets/actions and has a one-to-one relationship with a xib.