Loop through similarly-named Controls - objective-c

I have view0 through view25. I don't particularly want to have a 25-case switch, so is there a way to do something like this?
- (void)modifyViewNumber:(int)number
{
[view*number* dosomething];
}

Put the views in an array at startup.

You could put a tag on each view and use a for loop with the following method:
- (id)viewWithTag:(NSInteger)aTag

Nobody's suggested NSMatrix yet? This sounds like what it's made for.
The caveat is that the views must all be controls, such as text fields or buttons. Basically, look at its class reference and see whether it inherits from NSControl at some point. If it passes that test, then NSMatrix is an option. (Here's the list of all AppKit classes, to make this easy.)
To make a control into a matrix in IB, create one of the control in the usual way, then option-drag its resize handle. It won't appear to do anything at first, but keep dragging. Instead of resizing, your control will proliferate; it is now a matrix of cells instead of a single control.

Why don't you put the views into an array and obtain references to them using the array index?
- (void)modifyViewNumber:(int)number
{
UIView* view = [views objectAtIndex:number];
[view dosomething];
}

Many people have said use an array--I do this all the time, it's really the only way to go when using an interface builder, but I wanted to add a little.
Sometimes getting the values into the array can be tricky. There is usually a way to get an array of all controls on the screen. usually I'll grab that and iterate over it looking for a type of control with a certain naming pattern and collect those into my own array.
In this way, you can often add a new control with no code change whatsoever (always one of my favorite goals).

Create an array of views. Add each one, in order, then reference it by the array index.
If the numbers are not sequential, use a hash table.
Reflection might be an option, but could be slower (I'm not an Objective C guru, don't even know if that is practical).

I assume you're using Interface Builder to setup those views?
Someone may have to correct me on this, but I believe you can create an NSArray Interface Builder outlet in your class and then assign all your views to it. For example, you could declare "IBOutlet NSArray * views;" in your header file, and then use interface builder bindings to tie all 25 views to that property. They'll automatically be added to the array, and then you can cleanly iterate over it in your code.

Either use a collection or Reflection.

Assuming Interface Builder (otherwise straightforward as answered before). This is the best I could manage:
In .h:
{
UILabel *banner[NUM_BANNERS];
}
#property (nonatomic, retain) IBOutlet UILabel *banner0;
#property (nonatomic, retain) IBOutlet UILabel *banner1;
#property (nonatomic, retain) IBOutlet UILabel *banner2;
etc.
In .m:
- (void)viewDidLoad
{
banner[0] = banner0;
banner[1] = banner1;
banner[2] = banner2;
etc.
Then can access by array index. Remember to release.

Related

Multiple instances of a single content view in NSStackView

I am creating an application that need to have a progress window in which i want to dynamically insert a subview for each item being processed, like Finder's copy files panel window. And also remove it dynamically when processing is done.
I want to use the same NSViewController view for all sub views, and I'm using an NSStackView to manage the views.
But, to make the sub views stay in memory I have to keep a strong reference to them, and the only way I know of is to create a property for each sub view i need to display. Like this:
#propery (strong) NSViewController *myViewController1;
#propery (strong) NSViewController *myViewController2;
#propery (strong) NSViewController *myViewController3;
#propery (strong) NSViewController *myViewController4;
....
I would like to know if there is a better, more dynamic way of doing this? Or do I have to create x number of properties for sub views to know i have enough instances to allocate, because I can't tell how many process views the user will need when running the application and exporting items.
I would therefore like to dynamically allocate each subview AND create a strong reference to it. Is that possible? Or is there another way of doing what I want?
Please let me know if I'm being unclear, I'll gladly explain more to get help with this problem.
You can store the references to the view controllers in an NSArray. Arrays keep strong references to the objects which they contain.

Iterate/Loop through all properties of a class in Objective C

Possible duplicate: Looping through properties in a class
The problem is I have number of UILabels on each row upon a UITableView and I need to map the properties of my model class (which are of course NSStrings) to the label titles.
As there are multiple labels(More than 12, and it might increase later in my project), hence I was using a for loop to allocate all the labels. But for mapping the variables to the labels I have to hard code each time for the corresponding label.
Is there any way loop through all the properties of an class, so that I can declare them in an order and fetch them as an array and map it properly.
I have seen and understood the above possible duplicate link but it populates the code with as many switch cases as many times it is required to set. Instead of that is there any other alternative for concise and more clear coding using a loop.
Any help would be appreciated.
Happy coding.
If you're talking about UILabels, I will assume you want to use them via IB in Xcode, however you're creating them in code just because you can loop in code.
If so, you can think about using IBOutletCollection instead of IBOutlet like below:
#property (nonatomic, strong) IBOutletCollection(UILabel) NSArray *titleLabels;
the order in this array will be the same, as you add them in the IB ui.
Hope, this helps.

IOS - The correct way for using #import classes

I am writing a test project to learn to write everything in code. I want to do this way so that I can better understand what the Elements in Storyboard do for me behind the scene's
In my project I have several UIViewControllers which share the same UI elements. For Example I have a UITool bar at the top of the screen with several buttons in it.
Now I want to put that UIToolbar in a separate class so that I do not have to write it all out or copy n paste it in every controller.
Now I know I can achieve this by doing this:
#import "General_Add_ons.h" //the UIToolbar is properly set up in this file
#interface FirstViewController : General_Add_ons
and then I just use [self topToolBar]; //topToolBar is the name of the toolbar
Now I just want to clarify is this the best and or only way to this?
Somehow I feel I should be able to do this:
General_Add_ons *gao = [[General_Add_ons alloc] init];
[gao topToolbar];
Am I thinking about this the wrong way? The first way seems to be limiting in case I have multiple external classes.
Thanks in advance.
Your approach seem correct. If you have several UIViewController instances that need the same UI elements or other controller code, you can put those elements in a UIViewController subclass. In your case, I believe the class General_Add_ons is the UIViewController from which your subclasses will inherit.
This class (your General_add_ons) should have a property for the reusable toolbar, e.g.
#property (nonatomic, strong) UIToolbar *toolbar;
As an aside, class names in Cocoa, by convention are: prefix+capitalized words without underscores. Apple has a great reference on naming conventions.
EDIT
For clarification, you can subclass your custom subclass as many times as you need. For example in my code, I have a class CCFViewController that encapsulates common properties and behaviors that I want all of my view controllers to have. In the project, then, all of the view controllers inherit from that parent controller. Similarly, your toolbar will live in the superclass and the other controllers inherit from it.
I am not 100% sure but i think you should try it this way:
General_Add_ons *gao = [[General_Add_ons alloc] init];
[gao.topToolbar anypossiblemethodcall];

Syntax help, why put '_' before variables?

I've been running though some tutorials and often times I will see something like this.
in the .h
UIButton *_loginButton;
#property (retain) IBOutlet UIButton *loginButton;
Then in the .m it will be something like...
#synthesize loginButton = _loginButton;
So my question is what benefit does putting an _ before do? or why is it common practice? and lastly should I be doing this as well?
It's a convention that people sometimes use to denote private instance variables, or to separate instance variables from properties. You'll sometimes see names with a leading underscore used for private functions or methods. As far as I know, Apple reserves that convention for its own use and recommends that you not use it in order to avoid name collisions. For that reason, you'll sometimes also see names that have a trailing underscore instead of a leading one, i.e. foo_ instead of _foo.
Because its a local variable.
Some companies have internal requirements to write the local variables with _
I don't know which version this started with, but I've noticed that you don't need to have a actual variable declaration at all if you're just going to represent it as a property.
// Interface
#property (retain) IBOutlet UIButton *loginButton;
// Implementation
#synthesize loginButton
And then you can just use the property:
loginButton = (....)
self.loginButton = (...)
[self setLoginButton:(...)]
etc...
Now, whether one way or another is The Right Way depends on personal taste really. For something like this, it usually always falls in the "stay consistent and following whatever coding standards are in place by you (sole developer) or your company/group/team)" category.

Setting a property on a custom object through Interface Builder

I have a custom UITableViewController subclass which I use in two places in a nib file. What should I do if I want the two instances to have slightly different behavior? Of course in the code I can select one kind of behavior or the other based on the value of a BOOL, but how do I set that BOOL from Interface Builder, without having to write an Interface Builder plugin?
As of Xcode 6 there is a new way doing this. You can now give your view properties the attribute IBInspectable and then you can edit those properties in IB as you would with and standard view.
So for example:
#property (nonatomic, strong) IBInspectable BOOL
More details (also for the new attribute IBDesignable) in Apples documentation: https://developer.apple.com/library/ios/recipes/xcode_help-IB_objects_media/chapters/CreatingaLiveViewofaCustomObject.html
"User Defined Runtime Attributes" in the Identity inspector is probably what you're looking for. This seems to be new as of Xcode 4.2.
Unfortunately, there doesn't seem to be much (any?) documentation about this feature on the Apple Developer site. I was able to use it for a simple property set.
So far as I know, you can't set parameters in IB without writing an IB Plugin.
That said, you have two other options.
If it is as simple as a single BOOL, you're probably best off making it a property of the MyCustomViewController class and set it in code after you init:
customViewController = [[MyCustomViewController alloc]initWithNibName:#"CustomViewController" bundle:nil];
[customViewController setFunky:YES];
The other option is to create a protocol for a MyCustomViewDelegate. If you're not familiar with protocols, your header would look like this:
#class MyCustomViewController;
#protocol MyCustomViewDelegate
#required
-(BOOL)customViewShouldBeFunky:(MyCustomViewController*)customView;
#end
#interface MyCustomViewController : UIViewController {
NSObject<MyCustomViewDelegate> *delegate;
}
#property (readwrite, retain) IBOutlet NSObject<MyCustomViewDelegate> *delegate;
#end
Since it is an IBOutlet, you can wire up the delegate like any other delegate in Interface Builder.
Then call [delegate customViewShouldBeFunky:self] when you need to determine how your view should behave.
Have two subclasses is probably easier, and will be easier to document.
Here is an example of overriding properties and setting them in custom classes, this may help. The property code will work before awakeFromNib is called. So you may decide what you have to do based on the user's decision right in awakeFromNib.
https://stackoverflow.com/a/31094561/1699210