Duplicating UIView - objective-c

I can't figure out how could I duplicate UIView with its contents. Or is it even possible?
I have made and UIView with a label and a button inside a .xib file. Now I wish to copy this view n times only with different label text.
I'm trying to do this like this, but such way I only get the last object shown. _view1 is IBOutlet just like _view1Label.
NSMutableArray *Info = [[NSMutableArray alloc]initWithCapacity:number.intValue];
for(int i = 0; i != number.intValue; i++)
{
NSString *number = [NSString stringWithFormat:#"Zona%i ",[[NSUserDefaults standardUserDefaults] stringForKey:#"ObjectNumber"].intValue];
NSString *zona = [NSString stringWithFormat:#"%#%i",number, i+1];
NSString *parinkta = [[NSUserDefaults standardUserDefaults] stringForKey:zona];
_view1Label.text = parinkta;
_view1.hidden = false;
CGRect newrect = CGRectMake(_view1.frame.origin.x, _view1.frame.origin.y + (80 * i), _view1.frame.size.width, _view1.frame.size.height);
_view1.frame = newrect;
[Info addObject:_view1];
}
for(int i = 0; i != number.intValue; i++)
{
UIView *add = [Info objectAtIndex:i];
[self.view addSubview:add];
}
I guess you'll get the idea what I am trying to do, maybe my idea of doing this is totaly wrong, so could anyone help me get on the path on this ?

Load the view multiple times from the nib, adjusting the label contents on each copy you load. This is much easier, shorter, less prone to error than trying to copy the UIView contents in-memory which you're trying to do.
Here's an example of using UINib to access the nib contents:
UINib *nib = [UINib nibWithNibName:#"nibName" bundle:nil];
NSArray *nibContents = [nib instantiateWithOwner:nil options:nil];
// Now nibContents contains the top level items from the nib.
// So a solitary top level UIView will be accessible
// as [nibContents objectAtIndex:0]
UIView *view = (UIView *)[nibContents objectAtIndex:0];
// assumes you've set the tag of your label to '1' in interface builder
UILabel *label = (UILabel *)[view viewWithTag:1];
label.text = #"My new text";
So just repeat the above code for each nib instance you want.

if you wish to show n views then you have to create the view n times, inside the first for loop, you can not place a single view in multiple places

If you are created the first view through code then you can use the following method.
Change your for loop like:
for(int i = 0; i != number.intValue; i++)
{
NSString *number = [NSString stringWithFormat:#"Zona%i ",[[NSUserDefaults standardUserDefaults] stringForKey:#"ObjectNumber"].intValue];
NSString *zona = [NSString stringWithFormat:#"%#%i",number, i+1];
NSString *parinkta = [[NSUserDefaults standardUserDefaults] stringForKey:zona];
UIView *tempView = [[UIView alloc] init];
UILabel *tempLabel = [[UILabel alloc] init];
tempLabel.frame = _view1Label.frame;
tempLabel.text = _view1Label.text;
[tempView addSubview: tempLabel];
tempView.frame = _view1.frame;
_view1Label.text = parinkta;
_view1.hidden = false;
CGRect newrect = CGRectMake(_view1.frame.origin.x, _view1.frame.origin.y + (80 * i), _view1.frame.size.width, _view1.frame.size.height);
_view1.frame = newrect;
[Info addObject:tempView];
}

Related

Objective-C loop needed

I need some help on automating this with a loop (as I have 500+ buttons). The code is bellow. Thank you.
MyButton *button1 = [[MyButton alloc] init];
button1.name = #"One";
button1.controller = self;
button1.image = [NSImage imageNamed:button1.name];
_buttonArray = [[NSMutableArray alloc] init];
[arrayController addObject:button1];
MyButton *button2 = [[MyButton alloc] init];
button2.name = #"Two";
button2.controller = self;
button2.image = [NSImage imageNamed:button2.name];
_buttonArray = [[NSMutableArray alloc] init];
[arrayController addObject:button2];
Better to name the buttons with a pattern like: "Button125", etc.
Example code, not tested:
for (int i=1; i<= 500; i++) {
[MyClass createButtonNumber:i]; // Where MyClass is the class name this code is in.
}
+ (MyButton *)createButtonNumber:(int)number {
MyButton *button = [MyButton new];
button.name = [NSString stringWithFormat:#"Button%03i", number];
button.controller = self;
button.image = [NSImage imageNamed: button.name];
[arrayController addObject:button];
return button; // Just incase it is needed.
}
Note: The following code repeated for each button makes no sense and has been left out of the example code.
_buttonArray = [[NSMutableArray alloc] init];
for (NSInteger i = 1; i <= 500; ++i) {
MyButton *button = [[MyButton alloc] init];
button.name = ...; // Needs a method to convert from i to corresponding English words
button.controller = self;
button.image = [NSImage imageNamed:button.name];
[arrayController addObject:button];
}
You need an algorithm to convert from i to English words (e.g 1 to "One", 2 to "Two" etc). This can be done with an NSNumberFormatter with numberStyle set to NSNumberFormatterSpellOutStyle, see this for more info.
You still needs 500+ images named according to the buttons' names.
It's just a guess, but UITableView and UITableViewCell might be what you need. I can think of no sane reason to use 500 UIButtons.

Finding Color of a UIView Object and change the Color

Hello Guys actually i have a lot of UIView custom class objects as a subview of a UIViewController class view which is inside a UIScrollView. And i want to check colors of UIView custom class objects. code i use is given below:-
- (void) RectColorCheck:(id)sender
{
NSArray *subViews = [[NSArray alloc] init];
subViews = [self.scrollView subviews];
NSLog(#"array----%#",subViews);
for (viewCG in subViews)
{
if ([viewCG.backgroundColor isEqual: [UIColor darkGrayColor]])
{
[viewCG setBackgroundColor:[UIColor orangeColor]];
}
}
}
but it not works the subview array of viewCG is null.
And the below code which adds the custom class(UIView) objects in viewCG subviews:-
for (int i=0; i<[mapDataArr count]; i++)
{
X = [[[mapDataArr objectAtIndex:i] valueForKey:#"X"] intValue];
Y = [[[mapDataArr objectAtIndex:i] valueForKey:#"Y"] intValue];
W = [[[mapDataArr objectAtIndex:i] valueForKey:#"W"] intValue];
H = [[[mapDataArr objectAtIndex:i] valueForKey:#"H"] intValue];
circleVwObj = [[CircleView alloc] init];
circleVwObj.frame = CGRectMake(X,Y, W, H);
circleVwObj.tag = i;
circleVwObj.lbl.frame = CGRectMake(2,2, circleVwObj.frame.size.width, circleVwObj.frame.size.height/2);
circleVwObj.lbl.text = [[mapDataArr objectAtIndex:i] valueForKey:#"standId"];
NSLog(#"lbl text---%#", circleVwObj.lbl.text);
circleVwObj.lbl.font = [UIFont boldSystemFontOfSize:11];
circleVwObj.lbl.backgroundColor = [UIColor clearColor];
circleVwObj.lbl.textColor = [UIColor whiteColor];
circleVwObj.lbl.textAlignment = UITextAlignmentCenter;
circleVwObj.lbl.minimumFontSize = 11;
circleVwObj.lbl.adjustsFontSizeToFitWidth = YES;
circleVwObj.lbl.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[self.viewCG addSubview:circleVwObj];
}
If the subviews array is nil, it is very likely that self.viewCG is nil as well and hasn't been initialized.
Also, you should use isEqual: to compare colors. The == operator just compares pointer identity (which might actually give you the expected result in this particular case, but it's likely to break).

xcode 4 setting a lot of UIImageView's

I have 8 UIImageView in my view, all declared in the .h and .m.
I called them img01, img02, img03,..., img08
and I also have 8 pics, named 01.png, 02.png, 03.png,..., 08.png.
if I want to set the first imageView to the first pic I'll use the following command:
UIImage *image = [UIImage imageNamed:#"01.png"];
[img01 setImage:image];
What if I have a lot of UIImageViews and pics?
I tried to use this code but couldn't figure out how to do the last line of code.
int count = 1;
while (count <= 8) {
NSString *countString = [[NSString alloc]initWithFormat:#"%i", count];
NSString *picname = [NSString stringWithFormat:#"0%#.png", countString];
NSString *imgName = [NSString stringWithFormat:#"img0%#", countString];
UIImage *image = [UIImage imageNamed:picname];
[img01 setImage:image];
count++;
}
The code will only change the first imageView. I need it to change all the imageViews.
Create a NSMutableArray, and fill it with the UIImageViews. Currently you only set the first:
[img01 setImage:image];
You can do something like that:
NSMutbaleArray imageViews = [[NSMutableArray alloc] initWithCapacity:8];
for (int i = 0; i < 8; ++i) {
NSString *countString = [NSString stringWithFormat:#"%i", count];
NSString *picname = [NSString stringWithFormat:#"0%#.png", countString];
NSString *imgName = [NSString stringWithFormat:#"img0%#", countString];
UIImage *image = [UIImage imageNamed:picname];
UIImageView * view = [[[UIImageView alloc] init] autorelease];
[view setImage:image];
[imageViews addObject:view];
}

Gesture recognizers on subviews don't seem to work

I have code as the following:
- (void)setPosts:(NSArray *)posts
{
_posts = posts;
int totalHeight = 0;
for (TumblrPost *post in posts) {
totalHeight += post.thumbH;
}
dispatch_queue_t mainQ = dispatch_get_main_queue();
dispatch_async(mainQ, ^{
int cumulativeY = 0;
int postCount = 0;
for (TumblrPost *post in posts) {
NSArray* array = [[NSBundle mainBundle] loadNibNamed:#"ThumbnailView" owner:nil options:nil];
ThumbnailView* thumbnail = [array objectAtIndex:0];
thumbnail.frame = CGRectMake(0,cumulativeY,0,0);
thumbnail.userInteractionEnabled = YES;
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showMainImage:)];
[thumbnail addGestureRecognizer:gesture];
[self.multiThumbnailView addSubview:thumbnail];
[thumbnail loadUrl:post.url];
cumulativeY+=100;//post.thumbH;
if(postCount >=2)
break;
postCount++;
}
NSLog(#"Set posts method");
});
}
- (void)showMainImage:(UITapGestureRecognizer *)gesture
{
if(gesture.state == UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateEnded)
{
int thumbIndex = [self.multiThumbnailView.subviews indexOfObject:gesture.view];
self.selectedPost = (TumblrPost*)[self.posts objectAtIndex:thumbIndex];
[self performSegueWithIdentifier:#"ShowMainPost" sender:self];
}
}
multiThumbnailView is a UIView which I have in my storyboard and ThumbnailView is an xib/class combination which is a 100x100 square with a label in it that says 'test'.
When I run my code I get three boxes in a vertical line but the gesture recogniser doesn't fire when I click on my sub views. Everything has userInteractionEnabled ticked. I tried making a test gesturerecognizer on the main multiThumbnailView and that worked.
Please help!
My guess is that ThumbnailView is a subclass of UIImageView - which by default sets its userInteractionEnabled to NO.
Make sure that you set userInteractionEnabled = YES on every ThumbnailViewthat you want to intercept taps.
EDIT:
In addition, you set the frame of the ThumbnailView to be with size of (0,0).
That means that this view is basically invisible and thus won't intercept touches.
And finally, please don't do:
ThumbnailView* thumbnail = [array objectAtIndex:0];
Instead you can check the count of the array or simply:
ThumbnailView* thumbnail = [array lastObject];

objective c setting an object to a class that is not known

I have an array of view controllers (there are more that I have shown):
..
settings = [[settingsSettingTab alloc] initWithNibName:#"settingsTab" bundle:nil];
other = [[otherSettingTab alloc] initWithNibName:#"otherTab" bundle:nil];
..
NSArray *views = [NSArray arrayWithObjects:settings,other, nil];
I then loop through them and assign some details to them before pushing them:
for (int i = 0; i < views.count; i++) {
...
NSString *className = NSStringFromClass([[views objectAtIndex:i] class]);
Class myClass = NSClassFromString(className);
myClass *subView = (myClass*)[views objectAtIndex:i];
[self.scrollView addSubview:subView.view];
}
How can I assign the right class to the *subView. It worked fine when I had only one type of view in my array and then I just used:
settingTab *subView = (settingTab*)[views objectAtIndex:i];
But now I need to check and use the right one. I have googled the question, but I'm not sure of how I would describe it? (dynamic typing? Duck typing?) Any pointers would be really appreciated.
Thanks
EDIT:
Here is the whole code:
NSArray *titles = [NSArray arrayWithObjects: #"Basics", #"Colours", #"Shapes", #"Settings", #"Other", nil];
basics = [[basicsSettingTab alloc] initWithNibName:#"basicsTab" bundle:nil];
colours = [[colorsSettingTab alloc] initWithNibName:#"colorsTab" bundle:nil];
shapes = [[shapesSettingTab alloc] initWithNibName:#"shapesTab" bundle:nil];
settings = [[settingsSettingTab alloc] initWithNibName:#"settingsTab" bundle:nil];
other = [[otherSettingTab alloc] initWithNibName:#"otherTab" bundle:nil];
NSArray *views = [NSArray arrayWithObjects: basics,colours,shapes,settings,other, nil];
for (int i = 0; i < views.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i + 20;
frame.origin.y = 0;
CGFloat newWidth = 280;
CGFloat newHeight = 320;
CGFloat locx = 0;
CGFloat locy = 0;
CGRect panel = CGRectMake(locx, locy, newWidth, newHeight);
frame.size = panel.size;//self.scrollView.frame.size;
//subview.view.backgroundColor = [colors objectAtIndex:i];
NSString *className = NSStringFromClass([[views objectAtIndex:i] class]);
Class myClass = NSClassFromString(className);
myClass *subView = (myClass*)[views objectAtIndex:i];
[subView.view setFrame:frame];
subView.tabTitle.text = [titles objectAtIndex:i];
[subView.view.layer setCornerRadius:5.0f];
[subView.view.layer setMasksToBounds:YES];
subView.delegate = self;
[self.scrollView addSubview:subView.view];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * views.count, self.scrollView.frame.size.height);
pageControl.numberOfPages = views.count;
}
From your edit, we see that you have a property tabTitle on each of your custom view controllers. I would recommend that you create a new UIViewController subclass that implements tabTitle, and use that as the superclass for each of your custom controllers. That way your code only needs to know that they are all a MyTabViewController class (for want of a better class name!). So in your for loop:
MyTabViewController *subview = (MyTabViewController *)[views objectAtIndex:i];
[subview.view setFrame:frame];
[subview.tabTitle setText:[titles objectAtIndex:i]];
// ...
[self.scrollView addSubview:subView.view];
Everything else (view property for example) is defined by UIViewController, from which all your subclasses are descendants.
EDIT
Incidentally, I would be careful about the naming of your objects - your view controllers are not views. In particular, this might cause confusion where you have subview.view. Perhaps more appropriate would be subviewController.view, or even just controller.view?
The properties you are setting are common to all through since they all inherit from UIViewController.
replace:
myClass *subView = (myClass*)[views objectAtIndex:i];
with:
UIViewController *subViewController = (UIViewController *)[views objectAtIndex:i];
Also, do be careful about using the terms "view" and viewController" interchangably. They are not the same thing and can get very confusing/complex when you name things like they are.
If all of them are subclasses of UIViewController, then just use it:
****
frame.size = panel.size;//self.scrollView.frame.size;
//subview.view.backgroundColor = [colors objectAtIndex:i];
UIViewController* subView = (UIViewController*)[views objectAtIndex:i];
[subView.view setFrame:frame];
****
If you are not doing anything special to every view controller, then you just don't need to know exact class of it as long as it is subclass of some known class...
Hope it helps :)