Modify and redraw another UIView from the UIViewController - ios

I have a flow issue in my iOS app from my subclassed UIView to its parent UIViewController.
Basically, I have a nib called preferences. It contains two sliders, two labels, and another UIView that will display a shape dictated by the two scroll bars (Stroke and opacity). I successfully painted the subclassed ui to the screen by setting the custom class of the UIView to a separate UIView we'll call subView. I have setters/getters for the scroll bars and they print out their values. How do i let the uiview class (pointed at the ui nib object) to update and redraw since it isn't referenced in the parent preferences class? I tried syntax like this:
[code]
IBOutlet SubClassUIView *subclassUI
[/code]
to no effect. It seems best to point a custom class at the UIView.
Any suggestions and advice would be much appreciated.
TL;DR can't modify subclassed uiview from "parent" uiviewcontroller

Sorry folks, i figured it out.
In addition to passing in a custom class that shares the same type as the IBOutlet (such as a UIView),
there MUST be a link referencing every object in in the .xib to its parent. In this case, the parent UIViewController needed a reference from the custom class ui to a IBOutlet UI. From there, some simple casting from generic and boring UIView to the custom class's unique methods makes for a complete flow.

Related

Need clarification regarding MVC design pattern

I have a reusable UIView with its own .xib file. This UIView would be added to different UIViewControllers as subviews. In the MVC design pattern, my reusable UIView should contain only code for the user interface(UILabels, UIButons, etc..). What I'm confused about is setting up the UILabels and UIButtons. Is the ViewController that contains my UIView responsible for setting up my UIView's UIButton click events and what my UILabel displays? The problem I'm having now is that I have multiple UIViewControllers that reuse the same UIView, but they all implement the same code that sets up my UIView. This end up with lots of duplicate code across my UIViewControllers. If I move the setup code to my UIView to reduce the duplicate code, doesn't that violate the MVC design pattern? Is there a way to create a "Controller" thats only responsible for setting up my UIView so I could reuse my UIView and Controller inside my UIViewControllers?
Assuming that by setup you mean instructing the UIView on how to draw itself based on some object, this is exactly what the drawRect method is for. UIView also provides an initWithFrame method and you can even create your own initializer if you want. One more option is to create a function in your UIView subclass that will take what ever info you are displaying and will setup the view way you want. Something like: setupCustomViewWithMyObject(object).
All this to say that your setup code should be in your UIView subclass and you are not violating anything.

How to draw using Quartz 2D to my ViewController

This is sort of a beginner-level question. I have inherited an iOS project and it is implemented with a few ViewControllers with associated XIB files. The XIB files contain various widgets that are controlled by code in the ViewControllers (which I think is the standard way of constructing an app).
However, I need to do some custom drawing (rectangles, lines, circles, text) in between the widgets, and I'd like to use the Quartz 2D library to do this. I've never used Quartz2D, and most of the sample code I find is centered around the View, not the ViewController.
Most of it seems to do with implementing the "drawRect" method of your View. However, my ViewController does not have a "drawRect" function, as far as I can tell. Is there a way I can implement a "drawRect" function on my ViewController or whatever View it is controlling?
*** addendum:
I have researched and reminded myself that the operational UIView is a property of the UIViewController, and it seems like UIView is created automatically by the application and bundled together with my XIB and ViewController (I think we selected "also create XIB" when we were creating a ViewController, so the UIView is implied?). I don't see where this default UIView instantiation occurs. But I assume the way to draw to it is to subclass it?
If so, what is the cleanest way to subclass this UIView and get access to drawRect while maintaining the connection to the existing ViewController and XIB (or storyboard)? I inherited the project and this change needs to be low-impact.
Thanks for any help/thoughts.
Make a subclass of UIView and override -drawRect: to do your custom drawing. In the xib, select the view of your view controller, go to the Identity Inspector (third tab in the right sidebar in Xcode), and replace UIView with your custom subclass.

Cannot create outlet connections to subviews in Interface Builder (Xcode 5)

I know this appears to be a duplicate of some other questions, but the answers are not working for me.
I have created a single view app.
In the storyboard I added a subview to my main view.
I have a label on my main view and another label on my subview.
I have created a class of type UIView and added it as the custom class for the subview.
I can ctrl-drag my label on my main view to the main view controller class. But when I try to ctrl-drag my label on my subview to my custom class, I cannot get the connection to occur.
I have even typed the property information and tried to make the connection manually to no avail.
Things have changed a bit in the latest version of Xcode's Interface Builder. Can somebody tell me what I am missing? There is literally no code here. I am just testing trying to connect outlets to a subview with a custom class.
The first image shows that I have set up the custom class and added a property but I cannot make the connection.
The second image shows the main view label is connected in the main view's controller.
The third image shows that there are no outlet connections for the subview's label.
You can manually write the IBOutlet property declaration in the #interface of the custom view subclass, and assuming you've defined the base class of your subview in IB, then you can drag from the outlet circle in the code back to the control in the scene.
Or, as you point out, Warren Burton suggested both this technique and another in his answer to this other question, Can't Wire to Subview in IB.
The issue has to do with the File Owner of the View Controller. It is probably set up as being IOViewController, thus you can only make property connections in that .h file.
What you can do, is create another .nib file for the subview and put the subview in there. Then in that .nib file, make the file owner IOSubview. Property connections will work just fine there. Then just add the subview to your IOViewController programatically. Just remember to load the nib file from bundle first.
This is what I did (in Swift):
I Created a new ViewController (e.g. class MyViewController: UIViewController {})
In StoryBoard, I expanded the 'Scenes' (i.e. the tree view of all UI components) and selected 'MyViewController'
Using the 'identity inspector' I assigned the 'MyViewController' class (as oppose to the default UIViewController)
After that I was able to assign an action.
I suspect that for Obj-C it is similar process.
You don't create outlets in the subclass, you create the outlet on the view controller it is on. You need to #import the subclass into IDViewController.h and create an outlet there.
IDViewController.h
#import "IDSubclass.h"
...
#property (strong, nonatomic) IBOutlet IDSubclass *outletName;
Zoom your storyboard to 100%. If you zoom out, to say 50%, then the outlet connection won't work.

What superclass for a custom UI component?

I need to create a custom UI component that will satisfy the following:
it will contain a composition of UIViews, Labels, Button and a TableView.
it should be possible to instantiate it programatically - or - placing a UIView in nib editor and change the class in the inspector to my custom component class. (and it would the maintain/keep the main frame values from placed UIView)
I already started experimenting with it, I chose the UIView but it doesn't handle the ..cellForRow... cell method. On the other hand, if I use a UIViewController, then my class change in the inspector doesn't work and the app crashes.
Which one should I choose - UIView, UIviewController or NSObject?
I would go for UIViewController or UITableViewController, since you said you are having a tableView in it. If you do a UIViewController, you would probably have to include another UITableViewController inside it, using addChildViewController, as explained here
I believe the reason why your app is crashing is that you you changed your class superclass from UIView to UIViewController, but in the Interface Builder you still just have a UIView object. You need to change it to a UIViewController in the Interface Builder, and select your class as the File Owner.
If you intend this to be a stand-alone component, with all of the logic contained within the control, then I would base it on a UIViewController, like Apple does with the MFMailComposeViewController. If you want it to be strictly a view, with no built-in logic of its own, but instead delegates that logic, then use a UIView and delegate the table view methods to the controller that is using it.

Should UIViews have properties?

Using proper MCV with Objective-C can a UIView subclass have #propertys?
i.e. in the .h file
#class MyViewSubclass;
#interface MyViewSubclass : UIView
#property (strong, nonatomic) UILabel *labelLabel;
#property (strong, nonatomic) UILabel *valueLabel;
#end
or should this be done in a UIViewController subclass?
Thanks in advance.
It is most common to subclass UIViewController to manage the labels, fields, images, and other views within a view hierarchy. However, if you are creating a reusable component view that will be used throughout your application, then it's perfectly appropriate to subclass UIView and add properties to your subclass.
From Apple's iOS App Programming Guide:
View controller objects manage the presentation of your app’s content on screen. A view controller manages a single view and its collection of subviews. When presented, the view controller makes its views visible by installing them in the app’s window.
The UIViewController class is the base class for all view controller objects. It provides default functionality for loading views, presenting them, rotating them in response to device rotations, and several other standard system behaviors. UIKit and other frameworks define additional view controller classes to implement standard system interfaces such as the image picker, tab bar interface, and navigation interface.
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AppArchitecture/AppArchitecture.html#//apple_ref/doc/uid/TP40007072-CH3-SW1
It's good for views to have properties, but don't mix model logic into a view. The properties in a view should describe how the property looks, not what the property holds. I would avoid having a property named valueLabel in a view.
An example of view property names is UITableViewCell. It has properties imageView, textLabel, and detailTextLabel.
It's perfectly reasonable for a UIView subclass to have properties. You might need them to implement layoutSubviews, for example.
It is perfectly reasonable, also if you want to create a reusable component that allows for interaction and better flexibility, take a look at UIControl (which is a subclass of UIView)

Resources