Loop through variables by name objective C - iphone

can I loop through variables by it's name??
IBOutlet UIImageView *img1;
IBOutlet UIImageView *img2;
IBOutlet UIImageView *img3;
IBOutlet UIImageView *img4;
IBOutlet UIImageView *img5;
IBOutlet UIImageView *img6;
IBOutlet UIImageView *img7;
IBOutlet UIImageView *img8;
//then
for(int i = 1; i<=8;i++){
img+i = nil;
}
I know how to loop via tag, but is it posible to do it like this in objective C ??

Not directly, but you can add them to a temporary array or use IBOutletCollection

just for the record, you can do this (but dont do it, use the previous answer)
for(int i = 1; i<=8;i++){
SEL sel = NSSelectorFromString([NSString stringWithFormat:#"setImg%d:", i]);
[self performSelector:sel withObject:nil];
}

Related

iPhone UITextField inputView error: Assignement to readonly property

I am having issues when I want to assign UIPicker as inputView of UITextField. It shows error " Assignement to readonly property". Please help as I think it is not related to property sythesizing.
I have added my code below:
#interface DriverWaitingDetails : UIViewController<UITextFieldDelegate,UIPickerViewDataSource, UIPickerViewDelegate>
{
IBOutlet UILabel *baseLabel;
IBOutlet UITableView *driverTableView;
IBOutlet UIPickerView *basePicker;
}
#property(nonatomic, retain) IBOutlet UIPickerView *basePicker;
#property(nonatomic,retain)IBOutlet UILabel *baseLabel;
#property(nonatomic,retain)IBOutlet UITableView *driverTableView;
#end
Implementation Code:-
-(void)viewDidLoad
{
basePicker=[[UIPickerView alloc] initWithFrame:CGRectMake(0,100,320, 500)];
self.navigationItem.title=#"Driver Table";
baseLabel.userInteractionEnabled = YES;
basePicker.delegate = self;
basePicker.dataSource = self;
[basePicker setShowsSelectionIndicator:YES];
baseLabel.inputView=nil;
[super viewDidLoad];
}
Attached Screenshot:-
You are setting the input view of UILabel.
You declared baseLabel as UILabel not UITextField.
IBOutlet UILabel *baseLabel;
You have declared
IBOutlet UILabel *baseLabel;
UILabel inherits from UIView : UIResponder : NSObject and the property is defined in UIResponder:
#property (readonly, retain) UIView *inputView
As the property inputView is read only, you cannot assign any value to it.

IBOutlet UIImageView

I got 30 of these codes, with the same implementation:
// .h
#interface ViewController : UIViewController{
IBOutlet UIImageView *circle;
IBOutlet UIImageView *circle2;
}
#property (nonatomic, retain) IBOutlet UIImageView *circle;
#property (nonatomic, retain) IBOutlet UIImageView *circle2;
// .m
#implementation ViewController
#synthesize circle;
#synthesize circle2;
- (void)viewDidLoad
{
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
circle2 = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
}
And somewhere in my code, Im adding it as a subview.
My problem is,Is there a way to make it shorter, for it to be maintainable.
You can use one IBOutletCollection instead of 30 IBOutlets. You probably want to set the tag on each UIImageView though, so you can still tell them apart.
(This answer assumes you use a nib. Remove the lines where you instantiate the UIImageViews in viewDidLoad if so.)
If you use name like - Circle1.png, Circle2.png, then you can go for for loop for creating this in a loop.
Something like -
for (int i = 0; i < imageCount ; i++ ) {
circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:[NSString stringWithFormat: #"Circle%d.png" , i]]];
}
Is there a pattern to where you are putting these views in their superview? If so, you could use a for loop that goes to 30 and programmatically create the views and add them to their superview.
So for example:
for (i = 0; i < 100; i++)
{
UIImageView* circle = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"Circle.png"]];
[self.view addSubview:circle];
}
Would add 100 of the image views you would want. Of course you will need to adjust the positions of each of these views in the loop, but this is the general idea.
while creating this viewcontroller pass the frame as a parameter.thats the only thing changing rite??.the image is same and as there are no other properties .. it may work

How to select UIImageView with name of Object

I added 6 UIImageViews in Interface Builder.
Those are declared.
#property (nonatomic, strong) IBOutlet UIImageView *Image1;
#property (nonatomic, strong) IBOutlet UIImageView *Image2;
#property (nonatomic, strong) IBOutlet UIImageView *Image3;
#property (nonatomic, strong) IBOutlet UIImageView *Image4;
#property (nonatomic, strong) IBOutlet UIImageView *Image5;
#property (nonatomic, strong) IBOutlet UIImageView *Image6;
Those UIImageView' name has a rule - "Image" + number.
I want to select those ImageViews dinamically.
For example,
for (NSInteger i = 0; i < 6 ; i++) {
if(... condition )
{
//new
[[NSString stringWithFormat:#"Image%d", i+1] setHidden:YES]; //--(1)
}
else
{
[[NSString stringWithFormat:#"Image%d", i+1] setHidden:NO]; //--(2)
}
}
But, this code isn't correct.
Please tell me more good way.
jonkroll's suggestion to put your image views in an array is a good way to do it, and generally the highest performance.
Another way is to use key-value coding (KVC) to access your properties by name:
for (int i = 0; i < 6; ++i) {
NSString *key = [NSString stringWithFormat:#"Image%d", i + 1];
UIImageView *imageView = (UIImageView *)[self valueForKey:key];
imageView.hidden = condition;
}
Using the view tag, as Mark suggests, is a third way to do it. His answer is a little short on details, so I will provide some.
You can set the tag in your nib:
So you can set the tag of your Image1 image view to 1, and the tag of your Image2 image view to 2, and so on.
Then you can find an image view by its tag using the viewWithTag: method on your top-level view:
for (int i = 0; i < 6; ++i) {
[self.view viewWithTag:i+1].hidden = condition;
}
Create an array of your imageViews and iterate over them using fast enumeration:
NSArray *imageViewArray = [NSArray arrayWithObjects:self.Image1,self.Image2,self.Image3,self.Image4,self.Image5,self.Image6,nil];
for (UIImageView* imageView in imageViewArray) {
if(... condition ) {
[imageView setHidden:YES]; //--(1)
} else {
[imageView setHidden:NO]; //--(2)
}
}
typically you can use Tag to identify your views, instead of using the name of the view.
#property(nonatomic) NSInteger tag
see here:
https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html
once you've set the tag, you can then do things like
if(uiview.tag == kSomeButtonTag)

Loading nib view into another nib view

I have two UIViews, let me called them as A and B. A is the container of B and each one is created using Interface Builder.
I need to add my B view into A using interface builder, like this image:
The problem is that the view is loaded but it's empty, when I debugged it I saw that every component is created.
The B UIView class definition is:
B.h (ISMSliderCustomizable.h)
#interface ISMSliderCustomizable : UIView {
IBOutlet UIView *view;
IBOutlet UISlider *slider;
IBOutlet UILabel *minLabel;
IBOutlet UILabel *maxLabel;
IBOutlet UIImageView *tooltip;
IBOutlet UILabel *sliderValue;
}
#property (nonatomic, retain) IBOutlet UIView *view;
#property (nonatomic) float min;
#property (nonatomic) float max;
#property (nonatomic) float initialValue;
#end
B.m (ISMSliderCustomizable.m)
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[[NSBundle mainBundle] loadNibNamed:#"ISMSliderCustomizable" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[[NSBundle mainBundle] loadNibNamed:#"ISMSliderCustomizable" owner:self options:nil];
[self addSubview:self.view];
}
I need to add a UIView into another UIView which every UIView is created with IB.
I think the problem is UIView in b.xib is 320x480
but View B in a.xib is not
so it's not empty,it just out of range

label and textview not responding to setText:

I have two properties setup properly in Objective-C:
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UITextView *textView;
I have synthesised them and linked them in the NIB file however when I come to use them like:
if (row==0) {
NSLog(#"First text");
[self.label setText:#"LABEL 1"];
[self.textView setText:#"LABEL 1"];
}
else if (row==1) {
NSLog(#"Second text");
[self.label setText:#"LABEL 2"];
[self.textView setText:#"LABEL 2"];
}
The text is not changing however the NSLog is being called and not the setText: and I was wondering why...
It should be a IBOutlet for you to link them in xib.
Now that you updated your question, the problem may be you have not connected it to your viewcontroller's property. Hence the result. Add more details to your question.
Make sure that Xib and IBOutlet were correct linked.
Make sure that your label and testView are visible. You can set their background color red or other any color different with bg to check their visibility.
Make sure that the line "[self.label setText:#"LABEL 1"];" had ran. you can check the NSLog.
Make sure that the line "[self.label setText:#"LABEL 1"];" was running in main thread.
If your properties are outlets you should declare them as follows:
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UITextView *textView;
The behaviour you are seeing suggests that you haven't set up the outlet correctly.
FIRST METHOD:
It should be declared as an IBOutlet and you should link it to a label and textView in XIB as Praveen S has said.
SECOND METHOD:
Other option if it is not a label in XIB then you need to allocate and initialize the label to set its text i.e. to access its properties/methods/attributes.
UILabel *label = [[UILabel alloc] init];
[label setText:#"Text"];
label.frame = CGRectMake(0,0,20,20);
Hope this helps.