I have an option to disable ads in my app. When that option is enabled, ads should disappear. Now, the ads do in fact disappear when you leave a page that had ads on it and come back to it. But for one page, my MainMenuViewController, for some reason that page does not refresh and the ads stay. For the other pages where it does, when the ads are there, and when I leave that page and come back, the ad itself refreshes and displays a new ad, but for the main menu, it's always the same ad, so it's not refreshing. I have the same code in all my view controller, so I'm not sure why this one is causing trouble. Here are the important methods in the MainMenuViewController:
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (TestAppDelegate*)[[UIApplication sharedApplication] delegate];
if(appDelegate.isPremium==NO) {
self.adView = [[[MobclixAdViewiPhone_320x50 alloc] initWithFrame:CGRectMake(0.0f, 430.0f, 320.0f, 50.0f)] autorelease];
[self.view addSubview:self.adView];
}
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.adView resumeAdAutoRefresh];
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.adView pauseAdAutoRefresh];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidUnload {
[super viewDidUnload];
[self.adView cancelAd];
self.adView.delegate = nil;
self.adView = nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
[self.adView cancelAd];
self.adView.delegate = nil;
self.adView = nil;
}
If it just happens on that particular view, its probably because its being kept in memory and not being redrawn when you return to it. This is common especially if you are using a navigation controller to manage view controllers in a stack (root view controllers, for example, are always in the stack and tend to stay in memory until that memory is needed otherwise).
Why don't you force the view controller's view to be redrawn with setNeedsDisplay?
Related
I am trying to draw something in my custom view, but not sure why drawRect could not access its instance data. Here is the steps I tried.
Create a Mac OS X app, with using storyboard checked.
In the storyboard, delete the view, then add a new custom view under the view at the same place. (I tried if the view is not deleted, same).
Assign EEGView class to the newly added custom view.
then run. From the log information, you will notice that the drawRect could not access the instance data although the instance variables get initialized and updated.
In viewCtroller.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
myView = [[EEGView alloc] init];
//[self.view addSubview:myView];
//Start Timer in 3 seconds to show the result.
NSTimer* _timerAppStart = [NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:#selector(UpdateEEGData)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timerAppStart forMode:NSDefaultRunLoopMode];
}
- (void)UpdateEEGData
{
// NSLog(#"UpdateEEGData.....1");
// myView.aaa = 200;
// myView.nnn = [NSNumber numberWithInteger:myView.aaa];
// make sure this runs on the main thread
if (![NSThread isMainThread]) {
// NSLog(#"NOT in Main thread!");
[self performSelectorOnMainThread:#selector(updateDisplay) withObject:nil waitUntilDone:TRUE];
}else
{
[self.view setNeedsDisplay:YES];
}
NSLog(#"UpdateEEGData.....2");
[myView setAaa:400];
myView.nnn = [NSNumber numberWithInteger:myView.aaa];
// make sure this runs on the main thread
if (![NSThread isMainThread]) {
// NSLog(#"NOT in Main thread!");
[self performSelectorOnMainThread:#selector(updateDisplay) withObject:nil waitUntilDone:TRUE];
}else
{
[self.view setNeedsDisplay:YES];
}
}
-(void)updateDisplay
{
[self.view setNeedsDisplay:YES];
}
In my custom view class EEGView.m
#implementation EEGView
#synthesize aaa;
#synthesize nnn;
-(id)init{
self = [super init];
if (self) {
aaa = 10;
nnn = [NSNumber numberWithInteger:aaa];
NSLog(#"init aaa: %i", aaa);
NSLog(#"init nnn: %i", [nnn intValue]);
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
NSLog(#"drawRect is here");
NSLog(#"drawRect aaa: %i", aaa);
NSLog(#"drawRect nnn: %i", [nnn intValue]);
}
#end
Did I miss anything? Tested in Xcode 7.2 & 7.2. But if I leave the 'using storyboard' unchecked, it works.
Or is it a Xcode bug?
Any advice appreciated.
Thanks in advance.
If you've added EEGView view on storyboard, you shouldn't be also instantiating one in viewDidLoad. You've alloc/init'ed a new one, but it bears no relationship to the one that the storyboard created for you. So, the one created by the storyboard has drawRect called, but you're setting the properties in the separate instance that you created in viewDidLoad which was never added to the view hierarchy (and thus never will have its drawRect called).
When the storyboard instantiates the view controller's view, it will instantiate your EEGView for you. All you need to do is to hook up an IBOutlet for this view in order to get a reference to it from your view controller. (For example, you can control drag from the EEGView in the storyboard scene to the #interface for the view controller that you've pulled up in the assistant editor.)
I have an app that uses the UITabBarController and one of the tabs is supposed to be a full on camera view (similar to Instagram). When I launch the app and go to that view, most of the screen is blank and no image library picker/camera view loads. Any help would be greatly appreciated.
Here is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
imagePicker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
[imagePicker setDelegate:self];
[imagePicker setEditing:NO];
// Place image picker (camera viewing angle on the screen)
[self presentViewController:imagePicker animated:YES completion:nil];
}
Try putting that code in viewDidAppear instead -- that worked for me. Better yet, would be to put all but the last line in viewDidLoad, so it's only called once, and just put the last line in the viewDidAppear method. When you cancel the image picker (the only thing I tested), it will just reappear, since viewDidAppear will be called again, so you need to implement imagePickerControllerDidCancel: like this to keep that from happening:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:nil];
self.imagePicker = nil;
}
And, in your viewDidAppear, put in an if statement to see if the picker exists before trying to present it:
if (self.imagePicker) {
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
i started a single view template in Xcode 4.2(recently upgraded to Xcode 4.2 and ios5)
so now i have only one view controller.
I added a new class to the project which is a subclass of UIViewcontroller.
Now in the main controller class viewdidLoad method
- (void)viewDidLoad
{
// Override point for customization after application launch.
[super viewDidLoad];
[self presentQuizcontroller];
}
-(void) presentQuizcontroller
{
_QuizController = [[[Quiz alloc] initWithNibName:#"Quiz" bundle:nil] autorelease];
_QuizController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:_QuizController animated:YES]; // Do any additional setup after loading the view, typically from a nib.
}
the problem is in my Quiz class
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
the initWithNibName method does get called(i checked by using breakpoint) but it doesn't passes the condition of if(self) . and hence the view don't appears.
Any ideas?
Edit
After the first answer i tried this way too
- (void)viewDidLoad
{
// Override point for customization after application launch.
[super viewDidLoad];
}
-(void) presentQuizcontroller
{
_QuizController = [[[Quiz alloc] initWithNibName:#"Quiz" bundle:nil] autorelease];
_QuizController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:_QuizController animated:YES]; // Do any additional setup after loading the view, typically from a nib.
}
-(void) awakeFromNib
{
[self presentQuizcontroller];
}
same thing Quiz.m initwithnib name method does not passes the condition if(self).
I think you need to use awakefromnib.
Here is the Link for another StackOverflow post if you want to read more.
PresentModalViewController is depreciated, I think you should now use presentViewController instead of it.
Are you sure that "Quiz" is the name of your file? That string should be same as the name of your xib file, namely something like "QuizController" or "QuizViewController"
Make sure the xib file is properly connected to header/implementation files by checking:
Owner of the xib file should be set as the viewController
View on the xib file (the one above all if you have multiple views) should be connected to viewControllers view.
I have a strange issue on ios 4.3.I have one of my screen in landscape mode, a button click presents a popover.My popover has a search bar.Whenever keyboard appears it automatically pushes my popover bit up.When I resign the keyboard , popover reduces in height.This is the issue only on ios 4.3.While in rest of the ios , my popover doesnot reduces in height after keyboard dismissal.
None of the answers above worked for me. Apparently the keyboard scales the view and restores this scaling after the UIKeyboardDidHideNotification notification, making the presentPopoverFromRect method useless when applied handling this notification.
The way I solved it was by delaying the latter call as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
popup = nil; //my ViewController with UITextField
popover = nil; //my UIPopoverController
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(resizePopup:)
name:UIKeyboardDidHideNotification
object:nil];
}
- (void)doDelayedResize
{
[popover presentPopoverFromRect:myButton.bounds inView:myButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (void)resizePopup:(NSNotification*)note
{
[self performSelector:#selector(doDelayedResize) withObject:nil afterDelay:0.01];
}
I answered a very similar question here: UIPopoverController's view controller gets resized after keyboard disappears
The way I got around it was to observe the keyboard disappearing in the controller which controls the UIPopoverController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(presentSearchPopover) name:UIKeyboardDidHideNotification object:nil];
And then in -presentSearchPopover, present the UIPopoverController again (it's quite a seamless transition):
- (void)presentSearchPopover
{
self.searchPopoverController.popoverContentSize = CGSizeMake(width, height));
[self.searchPopoverController presentPopoverFromRect:someRect) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Don't forget to remove the observer in -dealloc or similar too:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[super dealloc];
}
I found an answer for this.It was a bug with the top arrow of popover.If I use the left arrow direction for popover, everything works fine.
I ran into this issue as well - specifically, the popover wasn't growing back to its pre-keyboard size after tapping away from the popover. (The popover would grow back if the user dismissed the keyboard directly or the popover's view controller resigned first responder).
Unfortunately, I have to use the top arrow direction for the popover due to the UI's layout. To solve this, the view controller responsible for the popover implements - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController. For example:
#interface MyController : UIViewController <UIPopoverControllerDelegate>
{
// ...
}
//...
#end
Set that controller as the popover's delegate:
MyPopoverViewController *popoverVC = [[MyPopoverViewController alloc] init];
UIPopoverController *myPopover = [[UIPopoverController alloc] initWithContentViewController:popoverVC];
myPopover.delegate = self;
// Hang on to popoverVC, myPopover or release them as desired...
In addition, my popover's view controller sets its contentSizeForViewInPopover property to the desired size:
#implementation MyPopoverViewController
- (id)init
{
self = [super init];
if (self)
{
// ...
self.contentSizeForViewInPopover = CGSizeMake(320, 400); // desired size
}
return self;
}
When the keyboard causes the popover to shrink, it affects the popover's popoverContentSize and not its view controller's contentSizeForViewInPopover. Therefore, reset popoverContentSize in MyController's delegate method:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
// Check if popoverController is valid, the popover you want, etc
popoverController.popoverContentSize = popoverController.contentViewController.contentSizeForViewInPopover;
}
Here is my solution:
1. Register for keyboard Notifications (UIKeyboardWillShowNotification, UIKeyboardWillHideNotification)
2. Create local variables:
CGSize _currentPopoverContentSize; //if you want to have custom size for popover
UIView *_currentPopoverSender; //to remember from wich view you will present popover
BOOL _keyboardIsShown; //enable in keyboardWillShow, and disable in keyboardWillHide
3. In my presentPopover method:
- (void)presentPopoverControllerWithSize:(CGSize)size fromView:(UIView *)sender{
MyController *controller = [[[MyController alloc] init] autorelease];
if (self.popover)
{
[_popover release];
_popover = nil;
}
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.popoverContentSize = size;
_popover.delegate = self;
//checking if keyboard is shown - if NO, than present popover, if YES - just `resignFirstResponder` for your _`activeTextField`(you can set it in -textFieldDidBeginEditing: and nullify in -textFieldDidEndEditing:)
if (!_keyboardIsShown)
{
[_popover presentPopoverFromRect:[sender bounds]
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
else
{
[_activeTextField resignFirstResponder];
}
_currentPopoverContentSize = size;
_currentPopoverSender = sender;
}
4. Than:
- (void)keyboardWillBeHidden:(NSNotification*)aNotification{
[UIView animateWithDuration:0.3
animations:^{
//do some stuff
[self.scrollView setContentSize:_scrollViewContentSize];
} completion:^(BOOL finished) {
if (_popover && _currentPopoverSender)
{
[_popover presentPopoverFromRect:[_currentPopoverSender bounds]
inView:_currentPopoverSender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}];
_keyboardIsShown = NO;
}
Hi After going through the forum, I don't think it's a bug after playing with frame sizes a lot, working on IOS 4,5,6,7 it's the same behaviour.
The solution for me was to:
1) Go into the designer by
2) Opening the XIB ViewController that is causing the problem (i.e. the PopOver one).
3) Click to select it's VIEW.
4) Uncheck "AutoResizeSubviews"
5) When loading the PopOver in code, make sure you do:
6) Your_Popup_Window.popoverContentSize = Your_ViewController.view.bounds.size;
I hope this helps.
Kind Regards
Heider Sati
I'm creating an iPad app. In it, I have a UITabBarController set up that shows 3 views. View 1, View 2, and View 3. This all works just fine. On View 1, the user is creating an order. They make then touch a button that builds the order. This is shown in a modal view that allows the user to review it before actually sending it. They can either "submit" or "edit" the order, either way, I dismiss the modal and return to View 1. That works fine as well. But if the user touches the "make" order button again, this time the loading of the modal view causes a crash "EXC_BAD_ACCESS". I copied the code just the same as I did for another modal view in the app, that has no problem showing itself time after time after time. I'm pretty perplexed at this point and would appreciate any help. Thanks. The code calling the modal is:
-(IBAction) makeOrder {
NSMutableArray *orderItems = [[NSMutableArray alloc] init];
//code that populates orderItems array - removed for brevity
NSLog(#"order items count:%d", [orderItems count]);
// Create the modal view controller
PartsOrderViewController *modalController = [[PartsOrderViewController alloc] initWithNibName:#"PartsOrderView" bundle:nil];
//this is the only difference b/w this and the other modal view. The other
//modal presents as a formsheet
modalController.modalPresentationStyle = UIModalPresentationFullScreen;
modalController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
modalController.orderList = orderItems;
modalController.storeId = selectedCustomer.storeID;
modalController.customerInfo = customerInfo.text;
modalController.customerTamsId = selectedCustomer.customerTAMSID;
// show the Controller modally -- This is the line that cause the error after the second time
[self presentModalViewController:modalController animated:YES];
// Clean up resources
[modalController release];
}
It actually gets into the viewDidLoad of the modal, but crashes as soon as that is finished running.
Here is the code for the modal:
#import "PartsOrderViewController.h"
#implementation PartsOrderViewController
#synthesize customerTamsId;
#synthesize customerInfo;
#synthesize invoiceDate;
#synthesize invoiceTime;
#synthesize storeId;
#synthesize customerInfoLabel;
#synthesize invoiceDateLabel;
#synthesize invoiceTimeLabel;
#synthesize storeIdLabel;
#synthesize orderList;
#synthesize delegate;
#pragma mark -
#pragma mark View methods
-(IBAction) editOrder {
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction) submitOrder {
//code removed for brevity
}
#pragma mark -
#pragma mark View implementation methods
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.customerInfoLabel.text = self.customerInfo;
self.storeIdLabel.text = self.storeId;
self.invoiceDateLabel.text = self.invoiceDate;
self.invoiceTimeLabel.text = self.invoiceTime;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
UPDATE: Solution found: Offending code is marked as such-
-(NSMutableArray *)buildOrderList {
NSMutableArray *orderItems = [[NSMutableArray alloc] init];
id cellObject = NULL;
int counter = 0;
NSEnumerator *theEnum = [self.partsList objectEnumerator];
while((cellObject = [theEnum nextObject]) != NULL)
{
GridTableCell *cell = (GridTableCell *)[self.partsListGrid cellForRowAtIndexPath:[NSIndexPath indexPathForRow:counter inSection:0]];
UILabel *lineAbbrev = (UILabel *)[cell.contentView.subviews objectAtIndex:0];
UILabel *partNo = (UILabel *)[cell.contentView.subviews objectAtIndex:1];
UITextView *orderQty = (UITextView *)[cell.contentView.subviews objectAtIndex:3];
//NSLog(#"OrderQty length: %d", [orderQty.text length]);
//NSLog(#"Part#:%#, OrderQty:%#", partNo.text, orderQty.text);
PartOrderIn *invItem = [[PartOrderIn alloc] init];
invItem.lineAbbrev = lineAbbrev.text;
invItem.partNumber = partNo.text;
invItem.orderQty = orderQty.text;
invItem.partMessage = #"";
if ([invItem.orderQty length] > 0) {
[orderItems addObject:invItem];
}
counter++;
[invItem release];
//The following three lines is what was killing it
//[lineAbbrev release];
//[partNo release];
//[orderQty release];
}
//NSLog(#"order items count:%d", [orderItems count]);
return orderItems;
}
At the risk of stating the obvious (sorry ;) did you step this through the debugger? Bad access is probably a memory allocation issue (again, mr obvious). How are the properties defined (is orderList retained? other properties?). Check where is crashes and note the values of your properties, either using Expressions in debugger or by memory address. My guess is something is not being retained that you assume is retained.
Nothing jumps out immediately (the problem is more than likely in the code you removed for brevity) but have you tried to enable zombies? How to enable zombies. This will usually give you some indication of the offender or at least gives you a hint of where to look...