This is driving me utterly insane.
I'm building an iPhone app and in my root view controller I have a UITableView.
In viewDidLoad I've set a background image for this table like so:
[self.view setBackgroundColor:[UIColor blackColor]];// this is so that I can see when the table background image does not show up.
UIImageView* backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"whiteBackground.png"]];
[backgroundView setFrame:CGRectMake(0, 0, 320, 460)];
[self.table setBackgroundView:backgroundView];
[backgroundView release];
My tableCells are transparent (or have background images themselves).
It works every second time I build the app and run it, both on the simulator and on an actual device.
It will show up fine, then when I build again it will show just the black background (but the table calls have their background images/transparency).
Has anyone ever experienced anything like this before? The fact that it is being picked up and displayed every second build makes me think there is something lurking in memory.
When I run it on a device/simulator and then quit the app normally (double tap home, hold the icon and tap closed) and then run it again it works fine. It seems to be something to do with killing the app when I build it each time. Note that I use the same exact code on another viewcontroller and it works every time, but it doesn't work on this - my root view controller.
Do you see the same if you move this code to viewWillAppear instead?
FWIW it would be better to set your backgroundView.frame to self.table.bounds rather than hard coding it to the size of the screen.
I've been banging my head against a wall to fix this and have found out a few things (as mentioned in my reply to Andrew Ebling's response). It's more than just the background image.
I had my project set up like so:
A UIViewController with a XIB.
Drop a tableView in the XIB.
Link up the Delegate and Data Source to the UIViewController.
Create a IBOutlet UITableView named 'table'.
Link that up in IB.
That has always worked just fine for me. But there is something weird going on with my 'table' IBOutlet being recognised 50% of the time. Every second time I build it is not recognised and reloadData is not run whenever I call it. It loads the table first time (meaning the datasource is intact) and cells can be selected (meaning the delegate is fine) but any selectors sent to 'table' are ignored.
This only happens on the RootViewController. Not on any subsequent view controllers in which I use this way of doing things.
So I just changed the class of my RootViewController to UITableViewController, changed the XIB accordingly (replace the uiview object with a uitableview and set the file's owner view property to the UItableview). Basically I just reverted back to what XCode gives you when you specify a new file with a UITableViewController subclass and a XIB for user interface.
That way I use self.tableView to reload instead of my own IBOutlet and it works fine.
I have no idea what caused this though and would like to know if it's a bug or not.
Related
Using XCode 4.4 and Mountain Lion,
I have a UIImageView, and on that view, I have a UIProgressView and a UIButton. When the app starts, the progress view and button are both hidden, as set in the storyboard. I then try to unhide them, first the progress bar when I'm doing something, and then the button when I'm done. I have called, for both items,
[self.view bringSubviewToFront:saveToCameraRoll];
to try to put them in front of the UIView.
Problem is, when I programmatically try to unhide them, it doesn't work. I can call:
progressBar.hidden = NO;
[self.view bringSubviewToFront:progressBar];
And that does nothing.
So then I tried to set everything as visibile in the storyboard and then programmatically set everything to be invisible once the controller loads. No deal; now my calls to hidden = YES seem to be ignored.
I then removed all actual programming, so that hitting buttons should just cause the button and progress bar to appear, reasoning that maybe the main thread was getting starved and couldn't update.
How can I force elements to pay attention to being hidden?
EDIT: I've now also tried programmatically modifying the alpha from 1 to 0. No change. It's like everything I'm doing is getting ignored. I made these items via the ctrl-drag method into the #interface section of the .m file; maybe I don't have some more delegates or interfaces or whatever hooked up?
As you said that you connected the ivars with your XIB file, it seems like your problem is that you are doing stuff on the main thread which in return blocks the run loop and your UI doesn't get redrawn anymore. When you update UI elements by changing their properties, those changes aren't applied instantaneous but the next time the UI gets redrawn which only happens when you give the main threads runloop a chance to run. However, if you do something like the following code, the changes will never appear:
[button setHidden:YES];
[self doSomethingReallyExpensiveAndTimeConsuming];
[button setHidden:NO];
The result of this code is that the button is set to be hidden, but doesn't get redrawn because the system has no chance to do it and when the system actually has a chance to redraw the UI, the button is already set to be invisible. A fix for this is to either split the work up and schedule it via timers on the main thread, or to use something like GCD to offload the work on a secondary thread (but then you need to make sure that your code is threadsafe!)
Is it possible the outlets are nil because they aren't hooked up in IB? If so, no amount of manipulation will have an effect.
Try NSLog(#"%#", saveToCameraRoll);
Is it null? Fix by reconnecting outlets in IB. If that works, then .hidden = NO will work and you can get rid of any code you added to manipulate the view hierarchy.
Kinda confusing title but oh well.
I have a UIScrollView in my viewController, in that is 3 UIViews with some buttons in each. I download data from a server and populate it into the view and this works as soon as you start scrolling the UIScrollView, but sometimes the buttons only partially load.
Usually its the button label without my formatting added to it. The button works and as soon as you click the button the rest of view loads correctly. Basically if the UIScrollView is touched in anyway it displays correctly.
I've tried adding and removing the scrollView to the view and I've called [scrollView setNeedsDisplay] and the exact same thing happens.
Anyone come across this?
EDIT: screen shot before and after (just basic to demonstrate whats happening)
I was building the buttons in drawRect which was causing issues. Built the buttons in a separate method and it worked fine.
I have application with a TabBar that controls several views. In one view, I control connections to different servers. Each server provides a different set of items.
I display these items in UITableView on another view.
The problem is that the tableview displays OK the first time but if I go back to view number one and change the server, thereby changing the list of items that should be displayed in tableview, the tableview becomes invisible for some reason. If I tap on the screen in the place where it should be, it becomes visible again.
I create table view like this
UITableView * aTableView = [[UITableView alloc] initWithFrame:CGRectMake(X,Y,Width,Height) style:UITableViewStyleGrouped];
[[self view] addSubview:aTableView];
aTableView.dataSource = self;
Ive tried to call reloadData and setNeedsDisplay in viewWillAppear of the UIViewController that hosts this tableview but without success.
Any advice?
Thanks
i don't know it will solve your problem or not but you are missing
aTableView.delegate = self;
or you haven't paste it here
I would guess that the problem is that tableview's datasource is not providing the data the first the table reloads after switching servers. If the datasource does not provide any rows, the tableview appears completely blank. That sounds like your issue.
I would look at the code where you switch servers as well as at the tableview:cellForRowAtIndexPath: Set a breakpoint/log there to activate after you switch servers and see what data the datasource is providing immediately after the servers switch. I think you'll find the table has no data. When you touch it, the table forces an update and by that time, the data has arrived.
I know this has been talked about a lot. I think I've gone thru every question on this site, and still have not been able to get this working.
I'm new to developing but I have a good sense of what's going on with all of my code. I definitely don't have a lot of experience though, this is my first iPhone app.
I'm making a data entry field that is comprised of multiple UITextFields within a UIScrollView. I'll avoid explaining the other details for now, as it seems its a very basic problem. Without a scrollview, the textfields work perfectly. I can touch the textfield and the keyboard or picker view show up appropriately. When I add the textfields to a scrollview, the scrollview works, but then the text fields don't receive my touches.
Here's the key: When 'User Interaction' is ENABLED, the scrollview works but the textfield touches are NOT registered. When 'User Interaction' is DISABLED, the scrollview doesn't work, but the textfield touches ARE registered and the keyboard/picker pops up.
From the other posts I have seen people creating subclasses and overriding the touches in a separate implementation. I've seen people using custom content views (subviews?), I've seen some solutions that are now obsolete since the APIs have changed in newer versions of the SDK, and I am just completely stuck.
I will leave out my code for now, because maybe there is a solution that someone has without requiring my code. If someone needs to see my code, I will put it up. My app is being written in the 3.1.3 SDK.
If anyone has ANY information that could help, it would be so greatly appreciated.
Here is what worked for me in Xcode 4.3.3.
In the storyboard, select your scrollview. Select Attribute Inspector on the right side. Uncheck Delays Content Touches.
It sounds like you're using IB to do a lot of your UI layout. If you take a programmatic approach you could set-up the following view hierarchy which should work.
Your view controller object managing your scroll view and your text fields should have a UIScrollView object and a UIView object (in addition to any UITextField objects you need). In the loadView method of the view controller class, allocate and initalize the UIView object and add your text fields to it as subviews. At the end of the method, allocate and initalize the UIScrollView object then add the UIView to the UIScrollView as a subview.
As an example, if your UIScrollView object were called scrollView and your UIView object called mainView the following lines at the end of the view controller's loadView method would properly set up the scroll view with the main view with the text fields on it:
scrollView = [[UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] bounds] ];
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = mainView.frame.size;
[scrollView addSubview: mainView];
self.view = scrollView;
You may need to enable / disable user interaction for both the scroll view and text fields as necessary.
If possible you might best using different touch mechanisms for each process (scrolling and textfield input).
Maybe you can check the time differential between touch start and end such that you can detect the difference between a drag (scroll) and a tap (text input).
Having said that if you propagate the touches up from the textfields to the scrollview you should be fine. One thing I use is:
[myObject addTarget:self action:#selector(itemTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
which passes the object touched so you can identify it and act accordingly.
I've made a ViewBased app, in the app delegate i've set a UITabBarCotntroller, in the app i have different view Controller two of them displays text in a UITextView and labels, the other one is my "ShakeController" a UIViewController in which i've set a UIAcelerometerDelegate, in it i create a instance of UIAccelerometer, in the method which manages the shake everything works fine, in this controller i have also set a UIImageView to make a simple animation, in the view Did Load method i set my imageView.animation to an array of UIImage.
My problem is : when the app is launched i use the ViewControllers and everything work fine, but when i tap the ShakeController item in the tab bar and then when i come back to the other controllers the label looks like : label and textView like : Lorem ipsum..... the text of UItextView in IB.
I have noticed thaht if i comment the initialisation of my imageView to the array of image i can navigate the items (from a view controller to another) without the label change and stay what i want them to be.
Notice that the two controllers are in a UINavigationController.
(i use #proprety (nonnatomic, retain) then #synthesize ... then releqse in the dealloc for the labels textview and my uiimageView)
Do not know what to do thanks to all
Quite hard to understand what you're asking here... I re-read it three times and I'm still not sure!
Since you find the problem (the data in the other view being "released") goes away when you comment out your imageView animation initialisation, I would conclude that you are using up a large amount of the iPhone's memory which means that it is automatically unloading any un-seen view controllers. It will do this quite quickly to preserve memory.
You don't say how many images are in your animation, but just 10 medium-large images can be enough to trigger memory issues; if you are wanting to use 20/30+ you have to look for another way.
You can try just loading a few frames into your image first and then swapping them out on a recurring timer. But if it's anything more than very basic animation you'll need to get stuck in to core animation instead: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/WhatisCoreAnimation.html#//apple_ref/doc/uid/TP40004689