issue with xib loaded in a Grect - iphone

learning much from you guys, and after a few hours I finally managed to load a xib into a GRect for a search xib that I built.
Basically, when you tap a cell in main.xib, it loads search.xib in a Grect so that I can filter down a list, click o nthe value, and place back into the cell in main.xib.
However I still have the cells from main.xib that overlay (tvcells) that overlay my search.xib.
Also it seems that none of the code is initializing for search.xib, I put an NSlog message in viewdidload in the search.xib, and nothing shows up in the console, letting me know that none of that code was executed.
Any idea why?
Thanks!
CGRect container = [[UIScreen mainScreen]bounds];
container.origin.x = 0;
container.origin.y = 0;
NSArray *views = [[NSBundle mainBundle] loadNibNamed: #"ingredientSearchViewController" owner: self options: nil];
UIView *referencedView = (UIView *)[views objectAtIndex:0];
referencedView.frame = container;
[self.subView addSubview:referencedView];
NSLog(#"loaded subview but obviously not in subview xib");
Additional code that attempts to do this as a controller
if (self != nil){
[self.view removeFromSuperview];
}
if(self == nil){
ingredientSearchViewController *vc = [[[ingredientSearchViewController alloc]initWithNibName:#"ingredientSearchViewController" bundle:nil] autorelease];
vc.view.frame = [UIScreen mainScreen].applicationFrame;
vc.delegate = self;
[self.subView addSubview:vc.view];
}

viewDidLoad is a method in NSViewController.
And you are creating a View from Nib, therefore you should use the equivalent method awakeFromNib for NSView.

Related

scrollsToTop not working with UIViewController containment

Using SDK 6.1, Xcode 4.6.1, I make a new project Master-Detail iOS App, ARC, no storyboards.
Then in the DetailViewController, in the viewDidLoad I add two UITableViews contained in UIViewControllers and make sure the second one is hidden like this:
- (void)viewDidLoad
{
[super viewDidLoad];
UIViewController *lViewController1 = [[UIViewController alloc] init];
UITableView *lTableView1 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView1.scrollsToTop = YES;
[lViewController1.view addSubview: lTableView1];
lTableView1.dataSource = self;
[self.view addSubview: lViewController1.view];
[self addChildViewController: lViewController1];
UIViewController *lViewController2 = [[UIViewController alloc] init];
UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView2.scrollsToTop = YES;
[lViewController2.view addSubview: lTableView2];
lTableView2.dataSource = self;
[self.view addSubview: lViewController2.view];
[self addChildViewController: lViewController2];
// now hide the view in view controller 2
lViewController2.view.hidden = YES;
}
(I make sure the DetailViewController is a datasource that returns 100 rows of UITableViewCells with the textLabel.text set to #"hello")
The presence of the second view controller makes that scrollsToTop (tapping on the status bar) does not work anymore. If I do not use UIViewController containment and just add two UITableViews and set the second one to be hidden, scrollsToTop does work.
What am I doing wrong?
scrollsToTop only works on a single visible view. From the documentation:
This gesture works on a single visible scroll view; if there are multiple scroll views (for example, a date picker) with this property set, or if the delegate returns NO in scrollViewShouldScrollToTop:, UIScrollView ignores the request. After the scroll view scrolls to the top of the content view, it sends the delegate a scrollViewDidScrollToTop: message.
You could try calling [tableView setContentOffset:CGPointZero animated:YES] on each of your table (or scroll) views manually instead. To do this, implement the scrollViewShouldScrollToTop: method in the UIScrollViewDelegate protocol:
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
[lTableView1 setContentOffset:CGPointZero animated:YES];
[lTableView2 setContentOffset:CGPointZero animated:YES];
return NO;
}
You can only set 1 ScrollView per ViewController with property .scrollsToTop = YES.
If you set 2 scrollview.scrollsTopTop = YES, it will simply stop functioning.
ie: your sample project (DetailViewController.m) update following lines,
line48: lTableView1.scrollsToTop = YES;
line56: lTableView2.scrollsToTop = NO;
then, scrollsToTop works correctly. If there are more than 1 scrollview you wish to concurrently setScrollsToTop, keep digging around. good luck!
I am currently experimenting with your project. When
lViewController2.view.hidden = YES;
is replaced with
lTableView2.hidden = YES;
then the scrolling works, even with controller containment.
I tried to insert a view between the controller's view and the table and then hide this view, but the table was not scrolling.
I tried to hide the controller by experimenting with shouldAutomaticallyForwardAppearanceMethods but the table was not scrolling.
Result: From my experiments, only one scroll view must be visible in the view hierarchy and the hidden property of the parent views is not checked out. hidden must be set to NO on all other scroll views, not their parent views.
After testing several options and various hits and try I finally settled to one final solution, i.e. setBounds: of scrollView (that is tableView in your case) and it works good. You'll have to put extra effort for animation although.
CGRect frame = scrollView.frame;
frame.origin.x = 0;
frame.origin.y = 0;
[scrollView setBounds:frame];
By the way in your case, try returning YES to
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
Although if not defined, assumes YES.
I have used this and now it works fine.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIViewController *lViewController1 = [[UIViewController alloc] init];
UITableView *lTableView1 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView1.scrollsToTop = YES;
[lViewController1.view addSubview: lTableView1];
lTableView1.dataSource = self;
[self.view addSubview: lViewController1.view];
[self addChildViewController: lViewController1];
lTableView1.tag=1;
UIViewController *lViewController2 = [[UIViewController alloc] init];
UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView2.scrollsToTop = NO;
[lViewController2.view addSubview: lTableView2];
lTableView2.dataSource = self;
[self.view addSubview: lViewController2.view];
[self addChildViewController: lViewController2];
lTableView2.tag=2;
// now hide the view in view controller 2
lViewController2.view.hidden = YES;
}
- (NSUInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSUInteger)section {
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * const kCellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"hello %d %d",indexPath.row, tableView.tag];
return cell;
}

Loading CustomView From nib file

I have a code that load the custom view from a nib file but there is a problem with the variable of that custom view.
- (id)initWithFrame:(CGRect)frame
{ self = [super initWithFrame:frame];
if (self) {
// Initialization code
HomeMainView* views = (HomeMainView*)[[[NSBundle mainBundle] loadNibNamed:#"HomeMainView" owner:self options:nil] objectAtIndex:0];
[self release];
NSArray* permission = [NSArray arrayWithObjects:#"user_photos",#"publish_stream", nil];
FBLoginView* fbLogin = [[[FBLoginView alloc] initWithPublishPermissions:permission defaultAudience:FBSessionDefaultAudienceFriends] autorelease];
[views.FBLogin addSubview:fbLogin];
[views.homeButton setTitle:#"asdf" forState:UIControlStateNormal];
self = views;
}
return self;
}
I am trying to add the fbLogin to the views object generated by the Nib file. The problem is the views.FBLogin generate the errors saying unrecognized selectors.
Does anyone know what is wrong here?
I had the same problem but it was because I needed to add this to my app delegate didFinishLaunchingWithOptions :
[FBLoginView class]
Without this the UIView was a UIView not an FBLoginView, hence the unrecognized selector.
Make sure that you have set the custom class in interface builder for the view. Select the view and press cmd+option+3 and set the custom class.

EXC_BAD_ACCESS when dismissing modalViewController iOS5

I've been scratching my head for a long time now, trying to solve this problem. I've searched StackOverflow, and have found people asking for something that resembles my problem like this question and this question, but none of the answers given have helped me.
To explain the problem in detail:
I've used Apple's Paging example to enable paging between view controllers
The View hierachy is as follows: UIWindow -> UIScrollView (MainController) -> UIViewControllers.
I use this code to create a delegate to the Viewcontroller containing the UISCrollview:
if(page == 0)
{
ContractsViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *) controller == [NSNull null])
{
controller = [[ContractsViewController alloc] initWithNibName:#"ContractsView" bundle:nil];
controller.delegate = self;
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (controller.view.superview == nil)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
controller.view.tag = 0;
[scrollView addSubview:controller.view];
}
}
The problem then occurs, when I try to present a modalviewcontroller from my ViewController inside the scrollview using the delegate. It works a few times, but then gives me a EXC_BAD_ACCESS. I've also tried posting a notification, and creating a listener in the MainController, to present it that way, but still the same problem.
When testing in iOS 4.3 everything works like a charm, but in iOS5 I get the issue.
I hope someone can help me get rid of this issue.
Thank you in advance.
As a start thank you for all your answers! I've finally found the solution to the problem.
As mentioned in my question, I used Apple's Pagecontrol sample as a template for my project. This template has a rootViewController which has an XIB with a window containing an UIScrollview and a Pagecontrol.
The problem happened, when I was trying to present the ModalView from a UIViewController inside the scrollview. I wanted to use the delegate, to present it through the rootViewController, but found out that it was using the UIScrollview to present it.
The UIScrollView object was apperently not retained, so after a couple of dismisses I hit the EXC_BAD_ACCESS.
I then figured, that i needed an UIView in the rootViewController, and placed it in the bottom viewhierachy in the XIB, and connected it with the view of the rootViewController. After I did that, I could use [delegate present..] and [delegate dismiss..] in the UIViewController without the EXC_BAD_ACCESS.
Yay! :)
I suggest removing your [controller release]; and adding an autorelease: controller = [[[ContractsViewController alloc] initWithNibName:#"ContractsView" bundle:nil] autorelease];
You don't own controller when it's returned from objectAtIndex:, so that way you could have the same behavior for both controllers, no releases.
I think I see your problem.. in the first if you release controller object and then you try to use it in the second if loop because of which you recieve this. release the controller object after both the if loops have passed.
EDIT:
try this code instead..
if(page == 0)
{
ContractsViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *) controller == [NSNull null])
{
controller = [[[ContractsViewController alloc] initWithNibName:#"ContractsView" bundle:nil]autorelease];
controller.delegate = self;
[viewControllers replaceObjectAtIndex:page withObject:controller];
}
// add the controller's view to the scroll view
if (controller.view.superview == nil)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
controller.view.tag = 0;
[scrollView addSubview:controller.view];
}
}
Try running the code with NSZombiesEnabled.
My guess is that the viewControllers object is either never initialised or is being released prematurely.
Also, there's this if (page == 0) wierdness:
if(page == 0) // <== only the first page ever gets the init code calling
{
ContractsViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *) controller == [NSNull null])
{
// ** SNIP **
[viewControllers replaceObjectAtIndex:page // <<=== always 0
withObject:controller];
[controller release];
}
// ** SNIP **
}

UITextView: Text only appears after I manually moved it

I have a very curious case (similar to this one):
I have a simple UITextView which is located in a UIView which I load programatically (NIB). Contents are loaded from a TXT file into the UITextView.text. This happens in the viewDidLoad.
Everything is fine if my text is only a couple of lines and if there is no need for scrolling. If the text is longer than the UITextView, however, the text will NOT BE DISPLAYED. Only if I touch the screen and try to scroll, will the text suddenly pop up.
I tried this nudge to get the text appear in the viewDidLoad:
textView.contentOffset = CGPointMake(0.0, 1.0);
textView.contentOffset = CGPointMake(0.0, 0.0);
But it won't work. I also made sure to call [super viewWillAppear] etc., but again, no luck. The only thing which helps a bit is if I init my view and load the text in the viewDidAppear. However, the last part of the UITextView is still not shown unless I scroll.
Any ideas why the UITextView is behaving this way? I have no clue and would be grateful for any suggestions as this is holding me up for days now.
EDIT:
I now know what is causing this strange behaviour, but I still don't know why this can be. The ViewController in which the PageView will be displayed is animated into view (simple animation block to slide the viewController into the screen). If I take away the animation, everything is fine. I have no idea why, though.
Here is a bit more code (not sure if it helps to clarify). This is the viewController where I init the view.
- (void)viewDidLoad {
[super viewDidLoad];
if (self.currentPageView == nil) {
NSLog(#"createPage...");
PageView *cpv = [[PageView alloc] init];
self.currentPageView = cpv;
[cpv release];
[self.view addSubview:currentPageView.view];
}
[self loadContentsFromTXTFile];
[currentPageView setTitle:title
date:date
text:text ];
}
This is the init of the PageView class:
-(id)init {
//self = [super initWithNibName:nil bundle:nil];
self = [super initWithFrame:CGRectZero];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"PageView" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
-(void)setTitle:(NSString *)title date:(NSString *)date text:(NSString *)text {
UILabel *mytitle = [self titleOfPage];
[mytitle setText:title];
UILabel *mydate = [self dateOfPage];
[mydate setText:date];
UITextView *mytext = [self textOfPage];
[mytext setText:text];
}
Ok, I solved this by simply using a UINavigationController to handle the views in which the problematic UITextView was found. I still don't understand why this has caused problems, but if you experience this problem, there may be something wrong with the structure of your UIViewControllers and the way they refresh (or don't refresh) the UITextView.

Removing superview in objective-c

I'm looking through an example in the iPhone Beginning programming book and they have code to switch between two views when a button is pressed. Here's the first snippet from their example code:
if (self.yellowViewController.view.superview == nil)
{
if (self.yellowViewController == nil)
{
YellowViewController *yellowController =
[[YellowViewController alloc] initWithNibName:#"YellowView"
bundle:nil];
self.yellowViewController = yellowController;
[yellowController release];
}
[blueViewController.view removeFromSuperview];
[self.view insertSubview:yellowViewController.view atIndex:0];
}
else
{
if (self.blueViewController == nil)
{
BlueViewController *blueController =
[[BlueViewController alloc] initWithNibName:#"BlueView"
bundle:nil];
self.blueViewController = blueController;
[blueController release];
}
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];
}
It does make sense to me, but the question I have is, how would you do this with a UISegmentControl that has four views. I know you can check for the selectedSegment and create that view when needed. But how would I know what the last view was in order to remove it from the superview beforing adding my new view as a subview? Thanks!
while creating each view either code or IB set tag value to segmentIndex.so u can get them later by that tag value.this is tricky and simple.
You could check to see which view is allocated or not nil and then remove.
if (yellowController) {
[yellowController.view removeFromSuperView];
[yellowController release];
}
You could go through your four views to determine which one is loaded and then remove the view.
For any UIView the frontmost subview is [[myView subviews] lastObject].