Add my UIView to a ViewController in Storyboard - iphone

I am new in iPhone development.
I have a UIViewController in storyboard that includes a scrollView.
I want to put two UIImageViews and some UILabels on it.
the idea that I am thinking is : create a .xib file. Put a UIView on it, an then set my UIImageview and labels on this UIView.
Finally add my UIView which is a .xib file to my UIScrollView.
Is it a good idea? if not what is your suggestion.
until now I could not make it works. this is my code:
OfferUIView *newPageView = [[OfferUIView alloc] init]; // UIView that I created as .xib
self.newPageView.contentMode = UIViewContentModeScaleAspectFill;
newPageView.frame = frame;
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
Can you help me?

I know it sounds stupid, but have you tried removing the self from self.scrollView and self.pageViews ?

How did you created your .xib file? it should be sub class of UIView. Hope you didn't do the mistake of creating it as a sub class of UIViewController.

I found the answer:
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"OfferView" owner:self options:nil];
UIView *newPageView = [views lastObject];

Related

Add a scrollView to a view in .xib file

I have an xib file includes a UIView and a UIScrollView.
Inside my UIView, I have another UIView (the while screen in the middle), and I want to add my scrollView to it programmatically.
The reason is one time I want to add a scrollView there and another time I want to add a mapView.
What I did is like this:
CGRect frame = self.view.bounds;
self.scrollView = [[UIScrollView alloc] initWithFrame: frame];
CGSize pagesScrollViewSize = self.view.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
I also need to set the delegate for the UIScrollView.
I could not make it work. this is my error:
-[UIScrollView setPageId:]: unrecognized selector sent to instance 0x7dd84e0
2012-10-06 00:56:17.373 testN[3525:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIScrollView setPageId:]: unrecognized selector sent to instance 0x7dd84e0'
I also don't know where should I connect the scrollView delegate. can you help me?
The error you're getting isn't in the code that you have pasted, it's because you probably have some code such as self.scrollView.pageId = ... somewhere else
Regardless of that, to help you achieve the effect you want you should probably add IBOutlet references for the MKMapView, UIScrollView and white UIView in the middle of the screen to your view controller.
You can also set the delegate of the scrollView in your xib file by right clicking on it and dragging the circle next to delegate (under Outlets) to the Files Owner (assuming the files owner is a UIViewController that implements UIScrollViewDelegate)
Then in viewDidLoad you'd have something like this
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.contentSize = self.scrollView.frame.size;
self.scrollView.frame = self.whiteCenterView.bounds;
[self.whiteCenterView addSubview:self.scrollView];
}
You shouldn't alloc/init a scroll view manually in code as you already have it there in the xib file and it will already be automatically created by the time viewDidLoad is called in your controller.
I can do that successfully by adding a UIScrollView in the interface builder and then set the delegate and file owner from there.
I just should note that since I want to add the UIView to a ViewController in storyboard this code will not work:
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"OfferView" owner:self options:nil];
UIView *newPageView = [views lastObject];
I should use:
UIView *newPageView = [views objectAtIndex:0];

Load XIB into a subview

I have been looking all over fo information on how to do this but have found nothing that I understand.
Basically I want to be able (from ViewController.xib) to load another XIB file on top of that view in a subview. This new subview should be manipulatable, so it can be moved around with multitouch gestures and/or swipe gestures.
I was trying to add a "view" object from ViewController, then load the other XIB into that subview object.
Hopefully someone can help. Thanks!
You should be able to accomplish what you want by making an instance of the other class in your ViewController, and then adding it as a subview to the current view controller.
MyOtherViewController *movc = [[MyOtherViewController alloc] init];
[self.view addSubview:movc.view];
As for handling the gestures, you could either handle them in the MyOtherViewController class, or make a container view and handle them it in your ViewController. Don't forget that they are subviews, and that any movement should be relative to their superviews.
The above code is almost right but except
UIView *newView = [[NSBundle mainBundle] loadNibNamed:#"MyNewXib" owner:self options:nil];
it should be
UIView *newView = [[[NSBundle mainBundle] loadNibNamed:#"MyNewXib" owner:self options:nil] objectAtIndex:0];
and in a view controller simply you can add
[self.view addSubview:newView];
You can define the subview in a xib by creating a xib (select File New... "user interface", "view").
You can load that view like this:
UIView *newView = [[NSBundle mainBundle] loadNibNamed:#"MyNewXib" owner:self options:nil];
That new view can now be treated like any other subview:
// assign it to a property
#property (strong, non atomic) UIView *viewFromXib;
#sythesize viewFromXib=_viewFromXib;
self.viewFromXib = newView;
// add it to your hierarchy
self.viewFromXib.frame = CGRectMake( /* this will start out 0,0 the size from the xib */ );
[self.view addSubview:self.viewFromXib];
// add gesture recognizer
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
[self.viewFromXib addGestureRecognizer:tapGR];
... and so on

Memory cost using UIViewControllers.view or UIView directly

Hi everyone, sorry my English is not good.
I have the next question: what is better to add a view (My question is about the cost of memory and better programing methods)
Like this:
UIViewController *vcToAdd = [[UIViewController alloc]
initWithNibName:#"vcxib"
bundle:[NSBundle mainBundle]];
[self.view addSubview:vcToAdd.view];
Or like this:
NSArray *xibsArray = [[NSBundle mainBundle]
loadNibNamed:#"MMList_iPhone" owner:nil options:nil];
UIView *vwToAdd = [xibsArray objectAtIndex:0];
[self.view addSubview:vwToAdd];
In the first case you own the UIViewController you create, this means you are responsible for releasing it. If you don't release it, there will probably be a leak somewhere.
UIViewController *vcToAdd = [[UIViewController alloc] initWithNibName:#"vcxib" bundle:[NSBundle mainBundle]];
[self.view addSubview:vcToAdd.view];
[vcToAdd release];
In the second case you DON'T own the content of the Nib file. So you aren't responsible for managing memory. Anyway, here you are getting the content of a Nib file and presenting it "as it is". Without a UIViewController that controls its behavior.
If the view contained in your Nib file needs some complex management, for example animations or getting touches, UIViewController way is probably what you're looking for...
Take a look at Apple's Memory Management Guide here and here (in English).
EDIT: There is a third way... Create your view programmatically without using Nib files.
// Create your content view
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)];
// Add objects to it
UIButton *button = [UIButton ...
UILabel *label = [UILabel ...
[view addSubview:button];
[view addSubview:label];
...
// Put your content view on screen
[self.view addSubview:view];
// Free memory
[view release];

iPhone: [subview release] removes my subview from the display

I have these two pieces of code. The first one works perfectly:
UIView *tmp = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 60.0f, 296.0f, 44.0f)];
[self.dynamicView addSubview:tmp];
[tmp release];
The second one is pretty much the same, but the view doesn't show up.
CommentBox *commentBox = [[CommentBox alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 296.0f, 44.0f)];
[self.dynamicView addSubview:commentBox];
[commentBox release]; // Why does this remove the view?
If I remove the [commentBox release] the view surprisingly appears. But I don't see a different between these two code snippets.
The init for the CommentBox looks like this:
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Load the nib:
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CommentBox" owner:self options:nil];
self = [nibObjects objectAtIndex:0];
}
return self;
}
After thinking about Graham's answer I came up with the following solution:
I drag a new UIView (-> lets call it sub UIView) in Interface Builder in my main UIView
I give this sub UIView the correct size (because I cannot resize the main UIView, which is always 320x460)
I drag all my other elements in this sub UIView (so that all elements are attached to my sub UIView)
I give my sub UIView a tag number (Interface Builder -> View Attributes), e.g. "300"
In the code I do now the following within my -initWithFrame:
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CommentBox" owner:self options:nil];
UIView *subView = [[nibObjects objectAtIndex:0] viewWithTag:300];
[self addSubview:subView];
Hope that helps.
Update:
I just had another idea of doing it. Instead of the tag numbers you can also create a IBOutlet UIView *viewHolder in the CommentBox class and set the outlet in IB. Then in the initWithFrame: I do the following:
[[NSBundle mainBundle] loadNibNamed:#"CommentBox" owner:self options:nil];
[self addSubview:self.viewHolder];
You're doing weird things in -initWithFrame:. I'm not 100% sure that it's causing the problem you report, but I'm pretty sure it's:
wrong; and
causing a memory leak.
I don't think replacing a view object with something dearchived from a nib in its -init… methods is a good idea. Either load the nib from a controller class, or have your initialiser load the object's subviews from the nib without replacing self.

UIImageView not displaying in UITableView header

My problem is that I can't seem to get the image from my bundle to display properly. This method is in the view controller that controls the tableview. headerView is loaded with the tableview in the .nib file and contains a few UILabels (not shown) that load just fine. Any ideas?
- (void)viewDidLoad {
[super viewDidLoad];
[[self view] setTableHeaderView:headerView];
NSBundle *bundle = [NSBundle mainBundle];
NSString *imagePath = [bundle pathForResource:#"awesome_lolcat" ofType:#"jpeg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
imageView = [[UIImageView alloc] initWithImage:image];
}
If you've already created an outlet and connected it to a view in Interface Builder, you should use that view, rather than creating a UIImageView on the fly.
//this assumes that headerView is an already created UIView, perhaps an IBOutlet
//also, imageViewOutlet is an IB outlet hooked up to a UIImageView, and added as
//a subview of headerView.
//you can also set the image directly from within IB
imageViewOutlet.image = [UIImage imageNamed: #"awesome_lolcat.jpeg"];
[[self view] setTableHeaderView: headerView];
FIrst you need to figure out whether your image is loading properly. The quickest way to get an image is to use the UIImage convenience method +[UIImage imageNamed: rawImageName].
Also, is this a UITableViewController? (it's unclear, but implied).
Where is imageView being used? You create it near the bottom, but don't seem to do anything with it. You probably want to create the image view, assign it an image, and then add it as a subview to the headerView.
//this assumes that headerView is an already created UIView, perhaps an IBOutlet
UIImage *image = [UIImage imageNamed: #"awesome_lolcat.jpeg"];
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
[headerView addSubview: [imageView autorelease]];
[[self view] setTableHeaderView: headerView];
Adding the subview programatically worked, but it isn't correctly linked to the UIImageView in Interface Builder. The view I created is (I think) correctly linked to the UIView outlet in my UITableViewController, but when I init my imageView it creates a new view instead of putting the image in the view I already created.
Thanks for your answer.
See http://developer.apple.com/library/ios/#samplecode/TableViewUpdates/Introduction/Intro.html
It will display UIImageview on section header.