Add same subview multiple times to view - iphone

I don't know if this is possible, but what I would like to do is add a subview several times to the view. I have tried something like this:
[self.view addSubview: newView];
newView.center = CGPointMake(160, 100);
[self.view addSubview: newView];
newView.center = CGPointMake(160, 200);
[self.view addSubview: newView];
All this does is move newView around, without adding new ones. Any ideas?
I also tried this:
[self.view addSubview:newView];
UIView *anotherView = newView;
anotherView.center = CGPointMake(160, 100)
[self.view addSubview:anotherView];
Edit
Here's a solution I've learned with time
Another way to solve the problem would be to make a separate nib containing the view and add instances of the nib several times. A good template to work off to implement this solution is to do it the same way a custom UITableViewCell is used in the cellForRowAtIndexPath method.

A view can only be contained in a single parent view's hierarchy. As soon as you add it to a new one, it is removed from the previous one. In this case, it is being removed and added back to the same view's hierarchy. You would need to make a copy of the sub-view to have it appear multiple times.

Related

iOS - Views inside other views

As I have told you many times, I'm new to iOS development.
I've learned something about views, view controllers, views hierarchy and stuff like that, and I'm thinking about one thing.
Assume that I want to create some app using some tab section, some table section, drawing canvas with context menu (quartz2D) etc, and I would like to have all these things visible at a time (static application) and can ensure some interaction between all these sections (changing something in the canvas results in some changes in the table, editing some values via context menu on canvas results in drawing a charts in tab pane and so on...).
The question is, if it is efficient to put all views on one screen and have some viewcontroller inside viewcontroller inside viewcontroller inside v...
How should I manage all particular views (with controllers) assuming that I have to present all of them at a time during entire application workflow?
/* PS. I'm new to StackOver as well, so let me know if such basic and not concrete questions like that one, are unwelcome */
You can't add ViewController inside a ViewController , you have one view Controller and on it's View you add SubViews Buttons, labels,...etc.
You can iterate on the subViews by get self.view.subViews
If you have a complex view, please make it as CustomView that inherits from UIView to make the code readable and well organized.
UIView *v1 = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 270, 400)];
v1.backgroundColor = [UIColor redColor];
UIView *innerView = [[UIView alloc] initWithFrame:CGRectMake(10, 20, 240, 370)];
innerView.backgroundColor = [UIColor greenColor];
[v1 addSubview:innerView];
[self.view addSubview:v1];
for (UIView *subview in self.view.subviews)
{
//You can get all subView object that You added
}

Strange three20's TTTableViewController frame properties

I am adding a TTTableViewController into an existing UIViewController, one strange thing I found is that the frame properties of the initialized TTTableViewController are wired, e.g. in a iOS layout.
I have:
UIStatusBar
UINavigationController
UIViewController
UITabBar
In order to set the TTTableViewController fill in all the remaining space I need to set the height to 460 instead of 367. (367 = 480-20-44-49)
e.g.
self.tableViewController.view.frame = CGRectMake(0, 0, 320, 460.0f);
instead of
self.tableViewController.view.frame = CGRectMake(0, 0, 320, 367.0f);
Why is it so?
*Edit for clarification: I mean TTTableViewController on the top of TTViewController (using [self.view addSubview:self.tableViewController.view];), and I need to set the self.tableViewController.view.frame = CGRectMake(0, 0, 320, 460.0f); instead of 367
It depends on when you are setting the frame, I think. I'm pretty sure when you set the frame in viewDidLoad, for example, you'll be setting it before the status bar and other things are taken into account. There might be other cases like this. If you set it to 320:460, it'll be resized to take into account the status bar and other stuff afterwards, making it fill in the rest of the screen. If you set it to 320:367 because you've already taken into account that stuff, it'll get resized again and squished (basically scaled down twice), making it only fill part of the screen. If you're using viewDidLoad you could try sticking it in another method (maybe viewWillAppear?) or just keep using 320:460.
It'd be nice to know when you set the frame, exactly. Also keep in mind that I could be way off. My mind's feeling a little fuzzy right now.
As per my understanding, only the size of your status bar is deducted i.e. 480-20 = 460. actually status bar is 22 pts but its approx.
Its just like when you add a viewcontroller to your navigation controller or your tab bar controller the size is auto rendered. So same is the case here, the three20 automatically adjusts the size of the view and if you try to set it to something smaller then that it behaves differently.
Its a nice question though. Happy Coding. Cheers!!
I wouldn't add a view of a different view controller into the main view of your current view.
You should present the TTTableViewController using the controller's present / dismiss functions. if you don't want to include the slide up effect, so the users won't see that it's a "different screen", use the boolean flag when you present the controller.
[self presentModalViewController:vc animated:NO];
Alternatively, use a TTTableView without the controller:
tableView = [[TTTableView alloc] initWithFrame:CGRectMake(0, kScrollViewHeight + kSignupLabelHeight, 320, kTableViewHeight) style:UITableViewStyleGrouped];
[tableView setBackgroundColor:[UIColor clearColor]];
tableView.delegate = self;
tableView.dataSource = [TTSectionedDataSource dataSourceWithObjects:
#"",
[TTTableTextItem itemWithText:#"Sign Up" URL:#"tt://signupController"],
nil];
[self.view addSubview:tableView];
Like a this code .
if use iOS6 , get current device.
if();
-(void)viewdidLoad{
TTTableViewController *tt = [TTTableViewController new];
CGRect frame = [UIScreen mainScreen].bounds;
tt.frame = frame;
tt.delegate = self;
[self.view addsubview:tt];
}

Removing table subview from Superview

Hi In my app Intially i loaded a view from app delegate. Next when some button click on this root view I added this code.
-(IBAction)method
{
View1 *v1=[[View1 alloc] init];
CGRect frame = CGRectMake(0.0f, 100.0f, 320.0f, 250.0f);
v1.view.frame=frame;
hideView = [[UIView alloc] initWithFrame: CGRectMake(0,0,320,480)];
hideView.backgroundColor = [UIColor blackColor];
hideView.alpha =0.8;
[hideView addSubview:v1.view];
[self.view addSubview:hideView];
}
In above code View1 is another view controller and hide view is just a view in root view controller. Now totally for Root view controller two views are added. Now my question is i want to remove the two added subviews from Root view when i clicked on table cell. how to do this? And also when i added this sub views to root view scrolling also not possible to table view and saying bad access error how to resolve this? Or any other ways to do this.
You can set unique tag to any view (subview) to easily retrieve reference to them later.
In your case, for example, you can add following lines:
v1.tag = 10112;
hideView = 10113;
And get references to that views later you can type:
//view - is a root view of that subviews
View1 *v1 = [view viewWithTag:10112];
UIView *hideView = [view viewWithTag:10113];
// and now you are able to remove them:
[v1 removeFromSuperview];
[hideView removeFromSuperview];
If View1 is inside hideView, so you can just call [hideView removeFromSuperView]; to remove both, or just use the #Nekto solution to recognize the view you want to remove.
For the scrolling issue, it's normal that if you add a view on top of the UITableView you're going to loss the table's scrolling, you could look at hitTest method of UIView.

Flipping between a standard and grouped style table via segmented control

I'm looking to use a UISegmentedControl to flip between two tables on the same view. One table (the default when the view is loaded) is grouped. The second table should be plain (non-grouped). The tableView is set to Grouped in the xib.
Right now I'm doing a reloadData when flipping between the two sets of data. So of course both "views" are in the grouped style. I know I can't change a tableView's style once set, but I'm looking to mimic that intent.
The best idea I've had is to create a second (plain) tableView in code, then flip between the two as needed. I could either show/hide (keeping them both in memory) or add and remove from the superView.
Both views may result in the user clicking through to additional pushed viewControllers. I want to retain consistency with the chain, including the ability to popToRootViewController from viewControllers further down the chain (the view in question is two or three steps down from the root).
Before I tear up my code with this idea I figure I'd check around to see what others thought.
Thanks!
UPDATE: Getting there. When I want to display the plain table view I have this:
PlainViewController *plainViewController = [[PlainViewController alloc] init];
UIView *plainTableView = plainViewController.view;
plainTableView.frame = CGRectMake(320, 0, 320, 480);
[self.view addSubview:plainViewController.view];
which loads and displays fine. But when PlainViewController's didSelectRowAtIndexPath fires, it fails to load the next view. didSelectRowAtIndexPath is firing (it's logged), but pushViewController does nothing; the next view's viewDidLoad never fires.
I suspect there's a discontinuity in the NavigationController but not quite sure where to fix that.
You can create a separate UIViewController and add its table to the 'main' view.
PlainTableViewController *ctr = [[PlainTableViewController alloc] init];
[self.view addSubview:ctr.view];
[ctr release];
You can also easily animate this process:
PlainTableViewController *ctr = [[PlainTableViewController alloc] init];
UIView *plainTableView = ctr.view;
plainTableView.frame = CGRectMake(320, 0, 320, 480);
[self.view addSubview:plainTableView];
[UIView animateWithDuration:0.3
animations:^{
groupedTableView.frame = CGRectMake(-320, 0, 320, 480);
plainTableView.frame = CGRectMake(0, 0, 320, 480);}
completion:^(BOOL finished){[groupedTableView removeFromSuperView];}
];
[ctr release];
Notice: You don't add it as view controller in your navigation controller so all calls of popToRootViewController should lead to your 'main' viewController. And that's what you want.
Assign your tableViewStyle in something like - (void) refreshTable; then when you tap your segmentedControl, also call [myTable reloadData];
You can use two different views that have table with both the style but with the same data and you can flip that two views on the segment selected index change event
OR
You have to remove the table from its superview and then realloc table with the selected style and add it again to that view.
I think that adding/removing the table views from the view containing the segmented control should work seamlessly.
In order to keep consistency, I think the approach is storing somewhere the information as to which view is selected through the segmented control, so that when you are displaying that view you know which is the current style. This info will be also stored in NSUserDefaults, so that it is persistent across runs.
Simple, every time that the segmented control changes, re-create the UITableView.
Upside: saves you from writing too much code, memory.
Downside: uses a bit more CPU.
But you'd be redrawing the view with reloadData anyway, so it is a very minimal CPU drain to simply recreate the view.
-(void)segmentedControlChanged{
CGRect originalFrame = tableView.frame;
UITableViewStyle tableStyle;
if(selectedSegmentIndex == 0){
tableStyle = UITableViewStylePlain;
} else {
tableStyle = UITableViewStyleGrouped;
}
[tableView removeFromSubview];
tableView = [[UITableView alloc] initWithFrame:originalFrame style:tableStyle];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
Note: code written by memory without checking in Xcode.

addSubview not working

// Create and add a sub view
CGRect viewRect = CGRectMake(0, 0, 200, 200);
UIView *a_sub_view = [[UIView alloc] initWithFrame : viewRect];
[window addSubview : a_sub_view];
After adding the above 3 lines of code, xcode produces no errors or warnings. But the sub-view is not showing at all. The sample program seems to be running exactly as before. Hope that somebody knowledgable could help.
I find it useful to set the background color so I know where the view is and the boundaries.
a_sub_view.backgroundColor = [UIColor redColor];
In your example, you're create an empty view so you won't 'see' anything.
window expects a viewcontrollers view to be added.
you can then add subviews to the current view.
so in your example use:
[self.view addSubview:a_sub_view];
I am using this in order to "find" the window:
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window addSubview:myView];
This also worked for me, but it is a bit uglier:
[self.navigationController.tabBarController.view addSubview:myView];
To explain the second one, I had to "follow" the controllers back up to the "top" view. (My application has a tab bar with a navigation controller inside the current tab.)
If you are working with iOS 5 & above , you have to do as below:
[self.window.rootViewController.view addSubView:viewObject];
[self.view addSubView: a_sub_view];