MVC and the use of a UIButton to dynamically create UI elements - objective-c

I understand the concept of MVC. At least I hope I do but there is a particular situation that I have encountered recently that makes me think that I actually have no idea.
Problem:
I am trying to create a class that when applied to an existing button adds the functionality of editing that button's title. It does so by dynamically generating a UITextField that will in turn be populated with the Button's new name. I hold the logic of adding the UITextField in a class called CustomAnimation and initializing it in the following way:
CustomAnimation *yar = [[CustomAnimation alloc] initWithButton:customButton];
The problem that I encounter is when I am trying to dynamically create a UIButton from a custom class like CustomAnimation and try to assign a target/action to it. Since the UIButton is actually generated inside the ViewController FROM the CustomAnimation class the former should get a pointer to the parent ViewController and then set it as the target.
[classButton addTarget:viewController action:#selector(dostuff:) forControlEvents:UIControlEventTouchUpInside];
All is good except one thing - dostuff method should reside inside the ViewController in order to be visible for that button and here everything turns into a hack.
What is the correct approach when you want to generate temporary UI elements from inside a Class instead of the Controller?
Thank you

There are lots of ways you can look at MVC in terms of granularity. If I understand your question correctly you are trying to implement MVC at a single control level which is - in my opinion - too finely grained. I try to aim for a more coarse approch where a controller manages a chunk of UI controls, e.g. a view or a window.
You could argue that the editability of the buttons label is bahavior that belongs to the button (encapsulated by it), hence its implementation is or should be part of the overall implementation of the button. Once you accept that, you could implement this as a subclass of UIButton and move the code that is in CustomAnimation to your subclass of UIButton. Or encapsulate CustomAnimation in your subclass of UIButton, whichever is more appriopriate.

Related

IOS custom button

I need a custom button like Instragram has in profile tab (the buttons that shows the number of photos and followers) but i don't know how to start to implement it.
Do i need to subclass UIButton or is there other way easier?
I think, the easiest approach would be to create a UIButtom with the typeUIButtonTypeCustom and add a subview to it with imageviews and labels as subviews to create the UI. Composition over inheritance.
Subclassing UIButton seems to me to be the obvious solution. I agree that subclassing UIViewController makes no sense. You don't use UIViewController objects to manipulate individual subviews within a view hierarchy controlled by another UIViewController object.
There are plenty of ways to do this, personally I would subclass UIViewController. Then you can edit its .xib in interface builder to make it look however you want and set different values programmatically. Then to detect a tap on the button you can just use the touchesBegan and touchesEnded (I'm pretty sure those aren't complete method names, check in the docs for more info on them) methods. If you want you could also set up a UITapGestureRecognizer for the view instead.

MVC and UIButtons

I have an iPad project I'm working on that dynamically creates a number of buttons that I need to add to the main view of my application. I was planning on firing a method that lives inside my View from my ViewController...say it's called add_buttons. It's my impression that in the MVC pattern, the view should handle the rendering of buttons and the general display, but the controller should handle the interaction. I'm also under the impression that it's bad design for the view to "know" about the view controller.
So I guess my question is, should I have my button tap logic contained in my controller? If so, how do I handle the separation? If I'm creating the buttons in my view, then it would have to have a reference to the view controller to use as the delegate for the event handler. If I create them in the controller, then I feel like I need to set certain UI elements in the controller which seems wrong to me. I know I'm missing something obvious but searching so far has proven fruitless.
Can anyone point me in the right direction?
The button tap logic most certainly belongs in the controller.
The code that creates the buttons probably belongs in the controller too. However, it would make sense to include a view method that returns a button with its appearance configured but not its behaviour.
Some general pointe:
View controllers and their view are very tightly coupled.
If in doubt it's best to put the code in the view controller.
A views interface should deal with primitive data types (e.g. strings, numbers, images). Views should not need to know the specifics of model objects.
Also, the naming convention for methods lowerCamelCase. Eg:add_button should be addButton.
when you add button to view,
[myButton addTarget:nil action:#selector(myButtonPressed) forControlEvents:UIControlEventTouchUpInside];
in view controller add
-(void)myButtonPressed {
}
with target:nil event will be handled by first controller containing this view
I rescently finished a project where I had to dynamically create UIViews which contained both UITextfields and UILabels.My approach to this problem was to call the "addViews" function from within the view controller. I figured this to be a better and easier approach rather than dealing with view controllers from inside the UIView. I have tested my approach and works completely fine (dynamically change UIView size and adding other UIViews with a UITextfield and a UILabel).

How to initiate display of one view from another?

Assume you do not have a UIController to do the job. From inside the UIView .. how would you replace self with another UIView?
It's not very clear what you are trying to do from your question. UIController is not a class, for instance.
Ideally your app should be structured something like this:
UIViewController subclass
Controls a set of objects that are all on screen at one time. For example, any number of UITextFields, UIButtons, UIViews and UILabels.
has methods (IBActions and other delegate methods) which are triggered by user interaction with the controls and inputs.
has IBOutlets which allow it to manipulate what the user sees on screen. For instance an IBOutlet attached to a UILabel allows changing the text when a user presses a button.
UIView is only generally subclassed if you need custom drawing code, or some kind of custom control. Don't put application logic here if you can help it, and you can usually help it.
You can have multiple UIViewControllers but they usually function very independently. Often View Controllers don't maintain references for other view controllers. If they do it's loose couplings like the delegate pattern.
Bottom line: if you have two views controllers that need to communicate with each-other, you need to have a reference to one from the other. This usually occurs in the form of a property on one or both of the view controllers, and is connected either by interface builder or at run time when you create them.
You can add another subview using self.addSubview: you may also want to check self.bringSubviewToFront:
For more information, check the docs:
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html

Should I use IB or Subclass UIView

So, I developed a kind of drop down button class.
Let's call it DDButton.
I mainly export one function :
-(void) addButtonWithImage:(UIImage*)image andTarget:(id)target andSelector:(SEL)selector
which lets the user add another button to the drop down.
I will need to use DDButton in different screens of my app.
I would like to use it like:
DDButton* ddb = [[DDButton alloc] initWithFrame:rect];
[ddb addButtonWithImage....]
[ddb addButtonWithImage....]
My question is since I never subclassed UIView before how should I implement it, and how should I use it later ?
Do I use IB and create a stub UIView which I'll connect to the DDButton in the Identity Pane ?
if so , how exactly I instantiate the view later on.
Or,
Do I subclass UIView ? if so , what methods I should override ? Do you I setup my buttons in the initializer ? in LayoutSubView ? In drawRect ?
I would love to hear the best approach here.
Thanks!
Edit
Let's say I choose the IB way : I have a main button which I set regardless of the
addButtonWithImage() calls, actually all calls to addButtonWithImage just "append" to that button. I want to main button to be the size of the view, until other buttons are added and then the view grows appropriately. However, I want the size of the view to be chosen by the user at first...using setFrame I guess.
Meaning in the awakeFromNib I can't count on the frame size yet (it only take the xib size I assume). So where would I setup my main button ? LayoutSubView ? setFrame ? I'm not sure.
Add your view to the interface in IB as a UIView, then change the class in the identity pane. If you need to do initialization in code, use a -(void)awakeFromNib method. I would suggest setting up the buttons when they are added in addButtonWithImage....
I'd probably do a subclass, building views in code is a good thing to learn.
Override drawrect: to do any custom drawing you need to do, if you're just adding a UIImageview or something and doing positioning you could just override initWith...: and do your custom initialisations.

Add a second image to a custom UIButton

I've got an Custom UIButton. It's got
a "static" background image
a variable text (the Title) which gets set in the code
Now I would like to add an icon (UIImage/UIImageView) inside the button on the left of the text. (I use the indent to move the text slightly to the right). Is there an easy way of adding that icon (and referencing it from code, so I can change it) or would you recommend creating a completely new button e.g. based on a UIView? (e.g. a view, that responds to touches)?
I'm just trying to get a feel for what the best approach would be for this. Any experience?
Two ways:
I prefer doing this by subclassing a UIView and (as you mention) implement the UITouch-responder methods. You're also able to override drawRect: what I really like because it makes your app soooooo much faster!
Since UIButton is a subclass of UIView, you can add a UIImageView to your button by using addSubview:. If you save it in your main-class (#property (...) UIButton *button) you can always access it by calling [self button]. You can also subclass your UIButton and add this #property. That's up to you.
It's totally up to you. However I prefer the first way!