My app crashes, not always, at the following method
// overridden
- (void)dismiss
{
[super dismiss];
[containerView_ removeFromSuperview];
containerView_ = nil;
}
crash happens at removerFromSuperview.
There is a "show" method as well
// overridden
- (void)show
{
if (self.parentView == nil)
{
// No parentView, create transparent view as parent
CGSize frameSize = [UIApplication currentSize];
containerView_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frameSize.height, frameSize.width)];
containerView_.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
containerView_.backgroundColor = [UIColor clearColor];
self.parentView = containerView_;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
if(some condition )
[[UIApplication sharedApplication].keyWindow.subviews.lastObject addSubview:containerView_];
else
[[UIApplication sharedApplication].keyWindow addSubview:containerView_];
}
else
{
[[UIApplication sharedApplication].delegate.window.rootViewController.view addSubview:containerView_];
}
}
[super show];
// This is done to allow the Cancel button to be pressed but nothing else - do after [super show]!
self.superview.userInteractionEnabled = YES;
}
It is strange, that code used to work. I am trying to compile the app for arm64, but I don't understand how that modification impacted those methods.
My app is a non-ARC app, and I cannot go to ARC right now.
Any ideas?
Change your code to dismiss view like this.
// overridden
- (void)dismiss
{
if(containerView_)
[containerView_ removeFromSuperview];
containerView_ = nil;
[super dismiss];
}
Please check with below code -
- (void)dismiss
{
if (containerView_)
{
[containerView_ removeFromSuperview];
containerView_ = nil;
[super dismiss];
}
}
Simply check if container view have superview
- (void)dismiss
{
if ([containerView_ superview])
{
[containerView_ removeFromSuperview];
containerView_ = nil;
[super dismiss];
}
}
My app shows articles from an RSS feed in a table view then when you select a row, opens a web view controller to show the article. I'm trying to add a loading indicator. If I select a row, the indicator will show briefly and then disappear before the page is fully loaded. Also, if I go back to the table view and select a different row, the loading indicator never shows up. I'm using a custom loading indicator called SVProgressHUD and it works fine elsewhere in the app. I don't think that is the problem though. What am I doing wrong?
Here is my didSelectRowAtIndexPath method in my table view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
}
The loading indicator is started on this line in viewDidLoad of the WebViewController:
[SVProgressHUD showWithStatus:#"Loading"];
And here is my WebViewController.
#import "WebViewController.h"
#import "TUSafariActivity.h"
#import "SVProgressHUD.h"
#implementation WebViewController
#synthesize webView=webView, hackyURL=hackyURL;
- (void)loadView
{
// Create an instance of UIWebView as large as the screen
CGRect screenFrame = [[UIScreen mainScreen]applicationFrame];
UIWebView *wv = [[UIWebView alloc]initWithFrame:screenFrame];
webView = wv;
NSLog(#"%#",webView.request.URL);
// Tell web view to scale web content to fit within bounds of webview
[wv setScalesPageToFit:YES];
[self setView:wv];
}
- (UIWebView *)webView
{
return (UIWebView *)[self view];
}
- (void) showMenu
{
NSURL *urlToShare = hackyURL;
NSArray *activityItems = #[urlToShare];
TUSafariActivity *activity = [[TUSafariActivity alloc] init];
__block UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:#[activity]];
activityVC.excludedActivityTypes = #[UIActivityTypeAssignToContact, UIActivityTypePostToWeibo, UIActivityTypeSaveToCameraRoll];
[self presentViewController:activityVC animated:YES completion:^{activityVC.excludedActivityTypes = nil; activityVC = nil;}];
}
- (void)toggleBars:(UITapGestureRecognizer *)gesture
{
BOOL barsHidden = self.navigationController.navigationBar.hidden;
if (!barsHidden)
{
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[self hideTabBar:self.tabBarController];
}
else if (barsHidden)
{
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self showTabBar:self.tabBarController];
}
[self.navigationController setNavigationBarHidden:!barsHidden animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[SVProgressHUD showWithStatus:#"Loading"];
UIBarButtonItem *systemAction = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(showMenu)];
self.navigationItem.rightBarButtonItem = systemAction;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(toggleBars:)];
[webView addGestureRecognizer:singleTap];
singleTap.delegate = self;
// self.hidesBottomBarWhenPushed = YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void) hideTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width;
}
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
view.backgroundColor = [UIColor blackColor];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height - 49.0;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width - 49.0;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
[UIView commitAnimations];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//stop the activity indicator when done loading
[SVProgressHUD dismiss];
}
#end
You should use the delegate functions of a webview see below
-(void)webViewDidStartLoad:(UIWebView *)webView{
//SHOW HUD
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
//KILL HUD
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
if(!webView.loading){
//KILL HUD
}
}
In webview normally caching happens, so HUD might not show for long as it will show for the first load.
I hope it will help you.
This is fixed. I just had to add
webView.delegate = self;
when I tested my App in instruments for memory leak I found nothing(running using simulator).But When I run it in a mobile and then checked, there are many leaks in UIKit objects. This happening in every view.In simulator no such leaks are showing.
Below is the screenshot of the instrument where some leakage happened.
When I moved to secondViewController from HomeView, no leaks found.If again coming back to home,these many leaks are found. So, is it mean that, I have to release/nil all the UI objects which I used in that secondView. For your information, below are the UI objects I used in secondView.
1.Two Background UIImageView
2.One TitleBar UIImageView
3.3 UIButtons(Back,left and right button for iCarousel)
4.One iCarousel view
5.UIPageController(For this I have used a third Party code SMPageControl)
6.One title label.
Note : Mine is Non-ARC code.
Did anyone faced this problem before.How can I overcome this problem,since I have this problem in every View in my App.Because of this, my App getting memory waring frequently and crashing often.
Thank you.
Below is the my implementation file of that View.
EDIT1 :
#implementation CatalogueViewController
#synthesize deptCarousel = _deptCarousel;
#synthesize carouselItems = _carouselItems;
#synthesize categorymAr = _categorymAr;
#synthesize spacePageControl = _spacePageControl;
#synthesize wrap;
- (void)dealloc {
_deptCarousel = nil;
[_categorymAr release];
_categorymAr = nil;
_deptCarousel.delegate = nil;
_deptCarousel.dataSource = nil;
[_deptCarousel release];
[_carouselItems release];
[viewGesture release];
viewGesture = nil;
[_spacePageControl release];
_spacePageControl = nil;
imgViewBG = nil;
imgViewBG2 = nil;
btnPrev = nil;
btnNext = nil;
// [self releaseObjects];
[super dealloc];
}
- ( IBAction) btnBackClicked {
[self.navigationController popViewControllerAnimated:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"catalogue", #"Catalogue");
// Do any additional setup after loading the view from its nib.
_deptCarousel.type = iCarouselTypeLinear;
_deptCarousel.scrollSpeed = 0.3f;
_deptCarousel.bounceDistance = 0.1f;
_deptCarousel.scrollToItemBoundary = YES;
_deptCarousel.stopAtItemBoundary = YES;
[_deptCarousel setScrollEnabled:NO];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeNext:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[viewGesture addGestureRecognizer:swipeLeft];
[swipeLeft release];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipePrev:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[viewGesture addGestureRecognizer:swipeRight];
[swipeRight release];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[viewGesture addGestureRecognizer:singleTap];
[singleTap release];
_carouselItems = [[NSMutableArray alloc] initWithCapacity:1];
_categorymAr = [[NSMutableArray alloc] initWithCapacity:1];
[self addCatalogues];
_spacePageControl.numberOfPages = [_categorymAr count];
[_spacePageControl setPageIndicatorImage:[UIImage imageNamed:IS_IPAD?#"Marker1.fw.png" : #"Markeri.png"]];
[_spacePageControl setCurrentPageIndicatorImage:[UIImage imageNamed:IS_IPAD?#"Marker-Highlight.png" : #"Marker-Highlight_i.png"]];
[_spacePageControl addTarget:self action:#selector(spacePageControl:) forControlEvents:UIControlEventValueChanged];
}
- (void)spacePageControl:(SMPageControl *)sender{
[_deptCarousel scrollToItemAtIndex:sender.currentPage animated:YES];
}
- ( void ) addCatalogues {
[_categorymAr addObjectsFromArray:[[DBModel database] categoryList]];
for (int i = 0; i < [_categorymAr count]; i++) {
[_carouselItems addObject:[NSNumber numberWithInt:i]];
}
[_deptCarousel reloadData];
}
- (void)viewDidUnload{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[self phoneType];
[super viewWillAppear:animated];
if (IS_IPAD) {
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self handleOrientation:statusBarOrientation];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- ( void ) phoneType{
if(!IS_IPAD){
if(IS_IPHONE5){
imgViewBG.image = [UIImage imageNamed:#"Background5_5.jpg"];
imgViewBG.center = CGPointMake(162,265);
imgViewBG2.image = [UIImage imageNamed:#"Background11_5.png"];
_spacePageControl.center = CGPointMake(160, 478);
_deptCarousel.center = CGPointMake(160, 355);
viewGesture.center = CGPointMake(160, 355);
btnPrev.center = CGPointMake(25, 355);
btnNext.center = CGPointMake(295, 355);
}
else{
imgViewBG.image = [UIImage imageNamed:#"Background5.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background9.png"];
}
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
textFieldSearch.placeholder = #"";
UIButton *clearButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[clearButton setImage:[UIImage imageNamed:IS_IPAD?#"Btn_X_Large.fw.png":#"Btn_X.fw.png"] forState:UIControlStateNormal];
[clearButton addTarget:self action:#selector(btnClearTextField) forControlEvents:UIControlEventTouchUpInside];
[textFieldSearch setRightViewMode:UITextFieldViewModeAlways];
[textFieldSearch setRightView:clearButton];
[clearButton release];
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
[textFieldSearch setRightView:nil];
if ([textFieldSearch.text isEqualToString:#""]) {
textFieldSearch.placeholder = NSLocalizedString(#"hud_search_for_a_product_here",#"");
}
}
-(IBAction)btnClearTextField{
textFieldSearch.text = #"";
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (IS_IPAD) {
return YES;
} else {
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation )toInterfaceOrientation duration:(NSTimeInterval)duration{
if (IS_IPAD) {
[self handleOrientation:toInterfaceOrientation];
}
}
- ( void ) handleOrientation:(UIInterfaceOrientation )toInterfaceOrientation {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
imgViewBG.image = [UIImage imageNamed:#"Background_Catalogue_P.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background_Overlay_P.fw.png"];
btnPrev.center = CGPointMake(90, 640);
btnNext.center = CGPointMake(677, 640);
textFieldSearch.frame = CGRectMake(187, 54, 418, 25);
_deptCarousel.frame = CGRectMake(235, 250, 300, 800);
_spacePageControl.center = CGPointMake(385, 920);
viewGesture.center = CGPointMake(385, 658);
}else {
imgViewBG.image = [UIImage imageNamed:#"Background_Catalogue_L.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background_Overlay_L.fw.png"];
btnPrev.center = CGPointMake(54, 385);
btnNext.center = CGPointMake(640, 385);
textFieldSearch.frame = CGRectMake(240, 55, 567, 25);
_deptCarousel.frame = CGRectMake(50, 250, 600, 300);
_spacePageControl.center = CGPointMake(346, 660);
viewGesture.center = CGPointMake(347, 405);
}
}
- ( IBAction )btnDepartmentClicked:(id)sender {
int btnTag = [sender tag];
ProductCategoriesViewController *productView = [[ProductCategoriesViewController alloc] initWithNibName:#"ProductCategoriesView" bundle:nil];
if ( btnTag == 0 ) {
[productView setStrTitle:NSLocalizedString(#"women", #"Women")];
}else if ( btnTag == 1 ) {
[productView setStrTitle:NSLocalizedString(#"men", #"Men")];
} else {
[productView setStrTitle:NSLocalizedString(#"sports", #"Sports")];
}
[self.navigationController pushViewController:productView animated:YES];
[productView release];
}
- ( BOOL ) textFieldShouldReturn:( UITextField * )textField {
[textField resignFirstResponder];
[Flurry logEvent:#"Product searched" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:textField.text,#"1", nil]];
[self productSearch:textField.text isBar:NO isQR:NO];
return YES;
}
- ( void ) productSearch:( NSString * )_searchText isBar:( BOOL )_isBar isQR:( BOOL )_isQr {
if ([_searchText isEqualToString:#""]) {
return;
}
NSMutableArray *ProductList = [[NSMutableArray alloc] init];
[ProductList addObjectsFromArray:[[DBModel database] productSearch:_searchText isBar:_isBar isQR:_isQr]];
if ( [ProductList count] == 0 ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"product", #"")
message:NSLocalizedString(#"cannot_find_product", #"")
delegate:nil
cancelButtonTitle:NSLocalizedString(#"ok", #"")
otherButtonTitles:nil];
[alert show];
[alert release];
} else {
GeneralProductListViewController *generalProductList = [[GeneralProductListViewController alloc] initWithNibName:IS_IPAD?#"GeneralProductListView~iPad": #"GeneralProductListView" bundle:nil];
[generalProductList setMArProducts:ProductList];
[self.navigationController pushViewController:generalProductList animated:YES];
[generalProductList release];
}
[ProductList release];
}
-(IBAction) spin:(id)sender {
if([sender tag]==0)
{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+1 animated:YES];
// [_deptCarousel scrollByNumberOfItems:1 duration:2.0];
}
else{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]-1 animated:YES];
}
}
-(void)swipeNext:(UISwipeGestureRecognizer *)recognizer{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+1 animated:YES];
}
-(void)swipePrev:(UISwipeGestureRecognizer *)recognizer{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]-1 animated:YES];
}
-(void) handleSingleTap:(UITapGestureRecognizer *)recognizer{
if ([_categorymAr count] > 0) {
ProductCategoriesViewController *prodCatView = [[ProductCategoriesViewController alloc] initWithNibName:IS_IPAD ?
#"ProductCategoriesView~iPad" : #"ProductCategoriesView" bundle:nil];
Category *categoryObj = [_categorymAr objectAtIndex:[self.deptCarousel currentItemIndex]];
[prodCatView setStrTitle:categoryObj.categoryName];
[prodCatView setCategoryId:categoryObj.categoryId];
[Flurry logEvent:#"Category List" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:categoryObj.categoryName,[NSString stringWithFormat:#"%d",categoryObj.categoryId], nil]];
[self.navigationController pushViewController:prodCatView animated:YES];
[prodCatView release];
}
}
//-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// pageControl.currentPage = [self.deptCarousel currentItemIndex] ;
//}
#pragma mark
#pragma mark NavigationBarViewDelegate metho
- ( void ) navigationBackClicked {
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark iCarousel methods
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
return [_carouselItems count];
}
- (NSUInteger)numberOfVisibleItemsInCarousel:(iCarousel *)carousel
{
//limit the number of items views loaded concurrently (for performance reasons)
return NUMBER_OF_VISIBLE_ITEMS;
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index
{
Category *categoryObj = [_categorymAr objectAtIndex:index];
//create a numbered view
UIView *view = nil;
NSString *imagePath = [[APP_CACHES_DIR stringByAppendingPathComponent:#"catalogues"] stringByAppendingString:[NSString stringWithFormat:#"/%d.jpg", categoryObj.categoryId]];
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
view = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:IS_IPAD?#"Gallery Placeholder.png":#"Gallery Placeholder.png"]] autorelease];
} else {
view = [[[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[APP_CACHES_DIR stringByAppendingPathComponent:#"catalogues"] stringByAppendingString:[NSString stringWithFormat:#"/%d.jpg", categoryObj.categoryId]]]] autorelease];
}
if (IS_IPAD) {
view.frame = CGRectMake(0, 0, 420, 420);
} else {
view.frame = CGRectMake(0, 0, 200, 200);
}
// UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(view.bounds.origin.x, view.bounds.origin.y+view.bounds.size.height, view.bounds.size.width, 44)] autorelease];
// label.text = categoryObj.categoryName;
// label.textColor = [UIColor blackColor];
// label.backgroundColor = [UIColor clearColor];
// label.textAlignment = UITextAlignmentCenter;
// label.font = [UIFont fontWithName:#"Helvetica-Bold" size:IS_IPAD?26:14];
// [view addSubview:label];
return view;
}
- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel
{
//note: placeholder views are only displayed on some carousels if wrapping is disabled
return INCLUDE_PLACEHOLDERS? 2: 0;
}
- (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index
{
//create a placeholder view
UIView *view = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]] autorelease];
UILabel *label = [[[UILabel alloc] initWithFrame:view.bounds] autorelease];
label.text = (index == 0)? #"[": #"]";
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.font = [label.font fontWithSize:50];
_spacePageControl.currentPage = index;
// [view addSubview:label];
return view;
}
- (CGFloat)carouselItemWidth:(iCarousel *)carousel
{
//usually this should be slightly wider than the item views
return ITEM_SPACING;
}
- (CATransform3D)carousel:(iCarousel *)_carousel transformForItemView:(UIView *)view withOffset:(CGFloat)offset
{
//implement 'flip3D' style carousel
//set opacity based on distance from camera
view.alpha = 1.0 - fminf(fmaxf(offset, 0.0), 1.0);
//do 3d transform
CATransform3D transform = CATransform3DIdentity;
transform.m34 = _deptCarousel.perspective;
transform = CATransform3DRotate(transform, M_PI / 8.0, 0, 1.0, 0);
return CATransform3DTranslate(transform, 0.0, 0.0, offset * _deptCarousel.itemWidth);
}
- (BOOL)carouselShouldWrap:(iCarousel *)carousel
{
//wrap all carousels
// return NO;
return wrap;
}
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index {
if (index == [self.deptCarousel currentItemIndex]) {
ProductCategoriesViewController *prodCatView = [[ProductCategoriesViewController alloc] initWithNibName:IS_IPAD ?
#"ProductCategoriesView~iPad" : #"ProductCategoriesView" bundle:nil];
Category *categoryObj = [_categorymAr objectAtIndex:index];
[prodCatView setStrTitle:categoryObj.categoryName];
[prodCatView setCategoryId:categoryObj.categoryId];
[Flurry logEvent:#"Category List" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:categoryObj.categoryName,[NSString stringWithFormat:#"%d",categoryObj.categoryId], nil]];
[self.navigationController pushViewController:prodCatView animated:YES];
[prodCatView release];
}
}
-(void) carouselDidScroll:(iCarousel *)carousel{
// [_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+3 animated:YES];
// [_deptCarousel scrollByNumberOfItems:1 duration:1];
}
- (void)carouselCurrentItemIndexUpdated:(iCarousel *)carousel{
_spacePageControl.currentPage = [self.deptCarousel currentItemIndex];
}
- ( IBAction ) myCart {
if ( [[DBModel database] isShoppingListEmpty] ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"at_shopping_cart", #"")
message:NSLocalizedString(#"amsg_shopping_cart_empty", #"")
delegate:nil cancelButtonTitle:NSLocalizedString(#"ok", #"") otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
MyCartViewController *myCartView = [[MyCartViewController alloc] initWithNibName:IS_IPAD ? #"MyCartView~iPad" : #"MyCartView" bundle:nil];
[self.navigationController pushViewController:myCartView animated:YES];
[myCartView release];
}
First, as noted before, use ARC. There is no single thing you could do that will more improve memory management.
Whether you use ARC or not, you should always use accessors to access your ivars (except in init and dealloc). As noted by #LombaX, you're setting your ivars incorrectly in viewDidLoad. Using accessors would help this.
You should run the static analyzer, which will help you find other memory mistakes.
I would suspect that you have an IBOutlet that is configured as retain and that you are not releasing in dealloc. That is the most likely cause of the leaks I'm seeing in your screenshots. ARC will generally make such problems go away automatically.
It is very possible that you have a retain loop. This generally would not show up as a leak. You should use heapshot to investigate that. Your leaks are pretty small; they may not be the actual cause of memory warnings. What you want to investigate (with the Allocations instrument) is what is actually significantly growing your memory use.
But first ARC. Then accessors. Then remove all build warnings. Then remove all Static Analyzer warnings. Then use the Allocations instrument.
Side note: the fact that it says the responsible party is "UIKit" does not mean that this is a bug in UIKit. It just means that UIKit allocated the memory that was later leaked. The cause of the leak could be elsewhere. (That said, UIKit does have several small leaks in it. In general they should not give you trouble, but you may never be able to get rid of 100% of small leaks in an iOS app.)
First:
you have a possible and visible leak, but I'm not sure if it is the same leak you have found in instruments:
These two lines are in your viewDidLoad method
_carouselItems = [[NSMutableArray alloc] initWithCapacity:1];
_categorymAr = [[NSMutableArray alloc] initWithCapacity:1];
But: viewDidLoad: is called every time the view is loaded by it's controller. If the controller purges the view (for example after a memory warning), at the second viewDidLoad your _carouselItems and _categorymAr instance variables will lost the reference to the previously created NSMutableArray, causing a leak
So, change that lines and use the syntesized setters:
self.carouselItems = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
self.categorymAr = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
the syntesized setter is configured to release the previous object before assignin a new one.
However: it's possible that you have another leak.
If you can reproduce the leak simply (if I understand, the leak appears simply moving from a VC to another), you can use the "heapshot" function of instruments.
Assuming that your leak appears moving from the first VC to the second and coming back:
open instruments with the allocations tool
go from the first VC to the second and come back.
press "mark heap" on the left. A line will appear.
go again from the first VC to the second and come back.
press "heapshot" again
do this several times (9-10)
the heapshot tool takes a "snapshot" of the living objects at the time you pushed the button and shows you only the difference.
If there are 2-3 new objects, you will see it in the list.
This is a good starting point to investigate a leak.
Look at the attached image:
Consider that you must mark the heap several time and discriminate "false positive" by looking at the object created, in my example you can se a possible leak (heapshot5, 1,66KB), but after looking at the content it's not --> it was a background task that started in that moment.
Moreover, delays of the autorelease pool and the cache of some UIKit objects can show something in the heapshot, this is why I say to try it several times.
One easy way to detect where your leaks come from is to use the Extended Detail view of the Instruments.
To do that click on "View"->"Extended detail" and a right menu with the stack trace of the "leak" will appear. There you will easily find the leaking code for each leak and if they come from your app.
I want my whole project to run in portrait mode only and only the view that's for viewing the photo's can turn on landscape same as if using the facebook (we view photo's they turn landscape also but other view's remains in portrait) i want to know that how it's done as i have a table view that has images that i get from the DB from the server and every particular data contains different number's of photo's so now i want that after the user select's the photo's they should open up fully and can be viewed in landscape and in portrait as well i did tried
I am working with ios6
- (BOOL)shouldAutorotate
{
return NO;
}
implementing in all the view's so that they can remain in portrait but still they turn in landscape how should i restrict it and please can any one tell me that in one of my class i have images in table view(loaded from the DB) and i have another class that open's up the selected photo from the table
My PhotoView.m class
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dic = [photos objectAtIndex:indexPath.row];
NSLog(#" *** url is %#",[dic objectForKey:#"url"]);
[self.delegate showPhotoAtUrl:[dic objectForKey:#"url"]];
}
My PhotoViewController.h class
#import <UIKit/UIKit.h>
#interface PhotoViewController : UIViewController <UIScrollViewDelegate>
{
NSString *url;
UIButton *doneButton;
}
#property (nonatomic, retain) UIImageView *imageView;
- (id) initWithPhotoUrl:(NSString *)photoUrl;
#end
and PhotoViewController.m class
#import "PhotoViewController.h"
#interface PhotoViewController ()
#end
#implementation PhotoViewController
#synthesize imageView;
- (id) initWithPhotoUrl:(NSString *)photoUrl
{
self = [super init];
if(self) {
url = [photoUrl retain];
}
return self;
}
- (void)dealloc
{
[url release];
self.imageView = nil;
[doneButton release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.tag = 1;
spinner.center = self.view.center;
[spinner startAnimating];
[self.view addSubview:spinner];
[spinner release];
[self performSelectorInBackground:#selector(loadPhotoData) withObject:nil];
doneButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[doneButton addTarget:self action:#selector(doneTouched) forControlEvents:UIControlEventTouchUpInside];
[doneButton setTitle:#"done" forState:UIControlStateNormal];
[doneButton setBackgroundColor:[UIColor clearColor]];
doneButton.frame = CGRectMake(2, 2, 60, 30);
[self.view addSubview:doneButton];
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.title = #"";
self.navigationController.navigationBarHidden = YES;
}
- (void) doneTouched
{
[self.navigationController popViewControllerAnimated:YES];
}
- (void) loadComplete:(NSData *)imageData
{
if(!imageData) return;
UIActivityIndicatorView *spinner = (UIActivityIndicatorView *)[self.view viewWithTag:1];
if(spinner) {
[spinner stopAnimating];
[spinner removeFromSuperview];
}
UIImage *img = [UIImage imageWithData:imageData];
float scale = MIN(self.view.frame.size.width/img.size.width, self.view.frame.size.height/img.size.height);
self.imageView = [[[UIImageView alloc] initWithImage:img] autorelease];
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width*scale, self.imageView.image.size.height*scale);
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.imageView.center = scrollView.center;
scrollView.delegate = self;
scrollView.contentSize = self.imageView.frame.size;
scrollView.minimumZoomScale = 1;
scrollView.maximumZoomScale = 2;
[scrollView addSubview:self.imageView];
[self.view addSubview:scrollView];
[scrollView release];
[self.view bringSubviewToFront:doneButton];
}
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void) loadPhotoData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
[self performSelectorOnMainThread:#selector(loadComplete:) withObject:imageData waitUntilDone:NO];
[pool drain];
}
#end
and in the main class i have have this method that calls the PhotoViewController to load the selected photo
- (void) showPhotoAtUrl:(NSString *)url
{
PhotoViewController *vc = [[PhotoViewController alloc] initWithPhotoUrl:url];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
Now my problem is how should i get the images after getting selected from the table to be open up in the same type of the view that open's up in FB app (open's the selected photo in portrait/landscape compatible view) i am only able to get one photo in my PhotoViewController class can any one tell me how can i add all the photo's to the PhotoViewController class so that i get the effect that i want ?... Any code help will be very helpful .. Thanks in Advance for contributing your time
In Short i have two things to do :
I have to restrict my project to only portrait mode leaving only the photo's view to have landscape/portrait compatibility.
I am currently having the photo's in my table view that i want on selection to open up in the same style(landscape/portrait compatibile) as FB or other app's do while viewing the photo's.
These only work on iOS 6.0
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationLandscapeLeft);
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
The method will return which orientation mode to use first.
Below are supportedInterfaceOrientations:
UIInterfaceOrientationMaskPortrait
UIInterfaceOrientationMaskLandscapeLeft
UIInterfaceOrientationMaskLandscapeRight
UIInterfaceOrientationMaskPortraitUpsideDown
UIInterfaceOrientationMaskLandscape
UIInterfaceOrientationMaskAll
UIInterfaceOrientationMaskAllButUpsideDown
For iOS > 4.0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Other ViewControllers will have
-(BOOL)shouldAutorotate { return NO; }
-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation{
return NO;
}
This is amongst the oddest issues with iOS development I have ever seen. I'm relatively new to iOS development, so I apologize if I'm missing something obvious or my terminology isn't completely correct. If you need clarification, please let me know in the comments and I'll edit my question accordingly.
The Problem
I'm using Three20, so that might have something to do with it. But I have a "Home view" which is basically a series of images that link out to other views (shown in the image below). If I start our in portrait view, all is well.
The next view is a table view, shown below:
YAY! I can rotate and all is right with the world. BUT if I go back to that home view, rotate to landscape, and THEN go to this tabled view, the world breaks.
You'll see that there's a random space added to the right side of my table now. I don't know where and how it came from. Here's my Controller.m file:
#import "FriendTabsController.h"
#import "MyAppApp.h"
#import "JohnDoeManager.h"
#implementation FriendTabsController
#synthesize innerView, segmentedControl, innerController, friendsController, friendRequestsController;
- (void)addBottomGutter:(UIViewController*)controller {
if ([controller isKindOfClass:[TTTableViewController class]]) {
TTTableViewController* tableViewController = (TTTableViewController*)controller;
tableViewController.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,50+44,0);
tableViewController.tableView.contentInset = UIEdgeInsetsMake(0,0,50+44,0);
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Friends";
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = nil;
friendsController = [[FriendsController alloc] init];
friendRequestsController = [[FriendsController alloc] init];
((FriendsController*)friendRequestsController).friendRequests = YES;
[self addBottomGutter:friendsController];
[self addBottomGutter:friendRequestsController];
innerController = friendsController;
[innerView addSubview:innerController.view];
[innerController viewDidLoad];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
[self loadBannerAd:(orientation)];
}
-(void) loadBannerAd:(UIInterfaceOrientation)orientation{
MainLayer *mi = [MainLayer getInstance];
if (mi.useJohnDoeAds) {
[[JohnDoeManager sharedInstance] setCurrentViewController:self];
[mi.JohnDoeBanner.view removeFromSuperview];
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
// This is a portait ad
if ([[MyAppUtils getCurrentDevice] isEqualToString:#"iphone"]) {
[mi.JohnDoeBanner setFrame:CGRectMake(0, 410-44, 320, 50)];
}else{
[mi.JohnDoeBanner setFrame:CGRectMake(0, 1024-44-90-20, 768, 90)];
}
} else {
// Landscape
if ([[MyAppUtils getCurrentDevice] isEqualToString:#"iphone"]) {
[mi.JohnDoeBanner setFrame:CGRectMake(0, 320-44-58, 410, 50)];
}else{
[mi.JohnDoeBanner setFrame:CGRectMake((1024-768)/2, 768-44-90-20, 768, 90)];
}
}
[self.view addSubview:mi.JohnDoeBanner.view];
[mi.JohnDoeBanner rollOver];
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self loadBannerAd:(toInterfaceOrientation)];
}
- (IBAction)didChangeSegment:(UISegmentedControl *)control {
if (innerController) {
[innerController viewWillDisappear:NO];
[innerController.view removeFromSuperview];
[innerController viewDidDisappear:NO];
}
switch (control.selectedSegmentIndex) {
case 0:
innerController = friendsController;
self.title = #"Friends";
break;
case 1:
innerController = friendRequestsController;
self.title = #"Requests";
break;
}
[innerController viewWillAppear:NO];
[innerView addSubview:innerController.view];
[innerController viewDidAppear:NO];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[innerController viewWillAppear:animated];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = nil;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[innerController viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[innerController viewWillDisappear:animated];
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[innerController viewDidDisappear:animated];
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[friendsController release], friendsController = nil;
[friendRequestsController release], friendRequestsController = nil;
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
So can someone please tell me what's going on? HELP!
You need to set wantsFullScreenLayout property to YES.
in your init methods set
self.wantsFullScreenLayout = YES;
This will solve your problem.