Singleton class for displaying iAds for iPhone - ios4

I have written a Singleton Class for managing iAds.The iAds pop up after 5 seconds of the user inactivity. The idleTimerExceeded call generate a notification to show the iAd. This code works fine for my requirements but since I am new to iOS development, my application sometimes hangs unexpectedly after integrating this code. This code results in lots of warnings etc. I would like to optimize my code in terms of memory and performance.
I would be very thankful for your kind suggestions and reviews.
Below is my code:
iAdSingleton.h
#import <Foundation/Foundation.h>
#import "AppDelegate.h"
#import "iAd/iAd.h"
#interface iAdSingleton : UIViewController<ADBannerViewDelegate> {
ADBannerView *adView;
UIViewController *displayVC;
NSTimer *idleTimer;
BOOL isItFirstTime;
}
#property (nonatomic, retain) ADBannerView *adView;
#property (nonatomic, retain) UIViewController *displayVC;
#property (nonatomic) BOOL isItFirstTime;
+ (id) shareAdSingleton;
- (void) resetIdleTimer;
- (void) idleTimerExceeded;
#end
iAdSingleton.m
#import "iAdSingleton.h"
#implementation iAdSingleton
static iAdSingleton* _sharedAdSingleton = nil;
BOOL bannerVisible = NO;
BOOL controlAccessBannerVisibility = NO;
#synthesize adView, displayVC;
#synthesize isItFirstTime;
#define kMaxIdleTimeSeconds 5.0
+(id)sharedAdSingleton
{
#synchronized(self)
{
if(!_sharedAdSingleton)
_sharedAdSingleton = [[self alloc] init];
return _sharedAdSingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([iAdSingleton class])
{
NSAssert(_sharedAdSingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedAdSingleton = [super alloc];
return _sharedAdSingleton;
}
return nil;
}
-(id)init
{
self = [super init];
if (self != nil) {
/* Initialize The Parameters Over Here */
//adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 480, 0, 0)];
adView = [[ADBannerView alloc] init];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
self.adView.delegate=self;
[self resetIdleTimer];
}
return self;
}
-(void)dealloc
{
displayVC = nil;
if (adView) {
[adView removeFromSuperview]; //Remove ad view from superview
[adView setDelegate:nil];
adView = nil;
}
[super dealloc];
}
-(UIViewController *)viewControllerForPresentingModalView
{
return displayVC;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
banner.hidden = NO;
if(!bannerVisible){
NSLog(#"Banner Changes 1 - Purpose: Visibility");
// [UIView beginAnimations:#"bannerAppear" context:NULL];
// banner.frame = CGRectOffset(banner.frame, 0, -100);
// [UIView commitAnimations];
bannerVisible = YES;
controlAccessBannerVisibility = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
//NSLog(#"Unable to receive Ad.");
NSLog(#"Banner Changes 2 - Purpose: Unable to Receive Ad.");
banner.hidden = YES;
if(bannerVisible){
[UIView beginAnimations:#"bannerDisappear" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, 100);
[UIView commitAnimations];
bannerVisible = NO;
}
}
- (BOOL) bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
NSLog(#"Pause anything necessary");
return YES;
}
- (void) bannerViewActionDidFinish:(ADBannerView *)banner
{
NSLog(#"We now resume to normal operations");
}
- (void)resetIdleTimer {
if (!idleTimer) {
idleTimer = [[NSTimer scheduledTimerWithTimeInterval:kMaxIdleTimeSeconds
target:self
selector:#selector(idleTimerExceeded)
userInfo:nil
repeats:NO] retain];
}
else {
if (fabs([idleTimer.fireDate timeIntervalSinceNow]) < kMaxIdleTimeSeconds-1.0) {
[idleTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:kMaxIdleTimeSeconds]];
/*
Notification: HideAd
*/
NSLog(#"Notification Generated For HideAd");
[[NSNotificationCenter defaultCenter] postNotificationName:#"HideAdBanner" object:nil userInfo:nil];
}
}
}
- (void)idleTimerExceeded {
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDel.adVisible == NO) {
NSLog(#"Notification Generated For ShowAd");
/*
Notification: ShowAd
*/
if (controlAccessBannerVisibility == YES) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ShowAdBanner" object:nil userInfo:nil];
}
}
}
#end

This is what you need. This code is thread safe as well as will not have any memory issue and warnings.
+ (iAdSingleton *) sharedInstance
{
static dispatch_once_t onceToken;
static iAdSingleton * __sharedInstance = nil;
dispatch_once(&onceToken, ^{
__sharedInstance = [[self alloc] init];
});
return __sharedInstance;
}

Related

CoreDataTableViewController does not reload on return from segue

I have several CoreDataTableViewControllers that utilize the helper class from Paul Hegarty's course. Everyone of them works except this one, and I cannot see a difference.
When the table first comes up, it is correctly populated and the segue executes properly when a cell is selected. However when I hit the back button, the table displays (null), (null) everywhere.
I have tried every variant of calling [self useDocument] that I can think of, still to no avail. Any thoughts? Thanks in advance.
//
// TeamTableViewController.m
//
#import "TeamTableViewController.h"
#import "iTrackAppDelegate.h"
#import "CoreDataTableViewController.h"
#import "SchoolRecords.h"
#import "ScheduleViewController.h"
#interface TeamTableViewController ()
#property NSInteger toggle;
#end
#implementation TeamTableViewController
#synthesize iTrackContext = _iTrackContext;
#synthesize schoolSelected = _schoolSelected;
-(void) setSchoolSelected:(SchoolRecords *)schoolSelected
{
_schoolSelected = schoolSelected;
}
-(void) setITrackContext:(NSManagedObjectContext *)iTrackContext
{
if(_iTrackContext != iTrackContext){
if (!iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
_iTrackContext = cdh.context;
} else {
_iTrackContext = iTrackContext;
}
}
[self useDocument];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"SchoolRecords"];
// no predicate because we want ALL the Athletes
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"schoolName" ascending:YES],
nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.iTrackContext
sectionNameKeyPath:nil
cacheName:nil];
__block NSInteger myCount;
int64_t delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.iTrackContext performBlock:^(void){NSError* requestError = nil;
myCount = [self.iTrackContext countForFetchRequest:request error:&requestError];
NSLog(#"In %# and count of iTrackContext = %lu", NSStringFromClass([self class]),(unsigned long)myCount);
}];
if (!myCount || myCount == 0) {
[self displayAlertBoxWithTitle:#"No Teams" message:#"Have you added athletes yet? \nPlease go to Add Athletes" cancelButton:#"Okay"];
}
});
}
- (void)useDocument
{
if (self.iTrackContext) {
[self setupFetchedResultsController];
} else {
NSString* errorText = #"A problem arose opening the search results database of Athletes.";
[self displayAlertBoxWithTitle:#"File Error" message:errorText cancelButton:#"Okay"];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
[self setITrackContext:cdh.context];
} else {
NSLog(#"In %# of %#. Getting ready to call useDocument",NSStringFromSelector(_cmd), self.class);
[self useDocument];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// If divide into sections use line below otherwise return 1.
// return [[self.fetchedResultsController sections] count];
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Do not really need this with only one section, but makes code usable if add sections later.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"teamInformation";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
SchoolRecords *schoolResults = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* titleText = schoolResults.schoolName;
cell.textLabel.text = titleText;
cell.detailTextLabel.text = [NSMutableString stringWithFormat:#"%#, %#", schoolResults.schoolCity, schoolResults.schoolState];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
# pragma navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
[self setSchoolSelected:[self.fetchedResultsController objectAtIndexPath:indexPath]];
// be somewhat generic here (slightly advanced usage)
// we'll segue to ANY view controller that has a photographer #property
if ([segue.identifier isEqualToString:#"scheduleDetailSegue"]) {
// use performSelector:withObject: to send without compiler checking
// (which is acceptable here because we used introspection to be sure this is okay)
NSLog(#"Preparing to passing school with schoolID = %#", self.schoolSelected.schoolID);
[segue.destinationViewController convenienceMethodForSettingSchool:self.schoolSelected];
}
}
- (void) displayAlertBoxWithTitle:(NSString*)title message:(NSString*) myMessage cancelButton:(NSString*) cancelText
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:myMessage
delegate:nil
cancelButtonTitle:cancelText
otherButtonTitles:nil];
[alert show];
}
#end
Well, I am not certain what the problem was. I ended up deleting the "offending" TableViewControllers in StoryBoard and recreated them. That did the trick. In retrospect, I wonder if I did not specify the wrong type of segue from my tabViewController. But I deleted it before I thought of that possibility.

IOS7 UIWebView does not rotate

I have simple UIWebView app that load the html, the problem is that the UIWebView does not rotate when I rotate the device.
Here is the ViewController.m
#import "WrapperViewController.h"
#implementation WrapperViewController
- (void) viewDidLoad
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle bundlePath];
NSString *fullPath = [NSBundle pathForResource:#"index"
ofType:#"htm" inDirectory:path];
[webView loadRequest:[NSURLRequest requestWithURL:
[NSURL fileURLWithPath:fullPath]]];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(BOOL)shouldAutorotate{
return YES;
}
- (void) didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation
{
webView.scalesPageToFit = YES;
webView.backgroundColor = [UIColor blackColor];
}
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void) dealloc
{
[super dealloc];
}
#end

Custom MKAnnotaionView, Display title/subtitle Position on Map

1) My annotation shows the title and subtitle of not.
I have already tried a lot, but I can not.
2) If an annotation has been selected, the annotation will be centered in the middle of the window. So the map is moved. Any idea?
3) My Callout button does not work anymore, I've got the # selector (openAnything) but I want to use this function is triggered - (void) mapView: (MKMapView *) mapView annotationView: (MKAnnotationView *) view calloutAccessoryControlTapped: (UIControl *) control {
Enough to ask, here's a video and some source code
http://www.youtube.com/watch?v=Ur1aqeYEFHw&feature=youtube_gdata_player
Thanks
TAPPMapViewControler.m
- (MKAnnotationView *)mapView:(MKMapView *)MapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[TAPPMapAnnotation class]])
{
static NSString *shopAnnotationIdentifier = #"Filiale";
//pinView = (MKPinAnnotationView *)
TAPPMapAnnotationCustom* pinView = (TAPPMapAnnotationCustom*)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotationIdentifier];
[self.myMapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotationIdentifier];
if (pinView == nil)
{
// if an existing pin view was not available, create one
TAPPMapAnnotationCustom *customPinView = [[TAPPMapAnnotationCustom alloc] initWithAnnotation:annotation reuseIdentifier:shopAnnotationIdentifier];
customPinView.image = [UIImage imageNamed:#"map_pin.png"];
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
TAPPMapAnnotation *theAnnotation = view.annotation;
TAPPMapAnnotationDetail *theController = [self.storyboard instantiateViewControllerWithIdentifier:#"MapAnnotationDetail"];
theController.theAnnotationId = theAnnotation.objectId;
[self.navigationController pushViewController:theController animated:YES];
}
TAPPMapAnnotationCustom.h
#import <MapKit/MapKit.h>
#interface TAPPMapAnnotationCustom : MKAnnotationView
#property (strong, nonatomic) UIImageView *calloutView;
#property (strong, nonatomic) UILabel *title;
#property (strong, nonatomic) UILabel *subTitle;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
- (void)animateCalloutAppearance:(BOOL)inAdd;
#end
TAPPMapAnnotationCustom.m
#import "TAPPMapAnnotationCustom.h"
#import "TAPPMapAnnotation.h"
#implementation TAPPMapAnnotationCustom
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
[super setSelected:selected animated:animated];
if(selected)
{
// Remove Image, because we set a second large one.
self.image = Nil;
UIImage *imageBack = [[UIImage imageNamed:#"map_pin.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 35, 0, 6)];
self.calloutView = [[UIImageView alloc]initWithImage:imageBack];
[self.calloutView setFrame:CGRectMake(0,0,0,0)];
[self.calloutView sizeToFit];
[self addSubview:self.calloutView ];
// Callout Button
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(openAnything) forControlEvents:UIControlEventTouchUpInside];
rightButton.frame = CGRectMake(0
, ((self.calloutView.frame.size.height-6) / 2)-(rightButton.frame.size.height / 2)
, rightButton.frame.size.width
, rightButton.frame.size.height);
self.rightCalloutAccessoryView = rightButton;
self.rightCalloutAccessoryView.hidden = YES;
self.rightCalloutAccessoryView.alpha = 0;
[self addSubview:self.rightCalloutAccessoryView];
// Start Annimation
[self animateCalloutAppearance:YES];
} else {
//Start Annimation and Remove from view
[self animateCalloutAppearance:NO];
}
}
- (void)didAddSubview:(UIView *)subview{
if ([[[subview class] description] isEqualToString:#"UICalloutView"]) {
for (UIView *subsubView in subview.subviews) {
if ([subsubView class] == [UIImageView class]) {
UIImageView *imageView = ((UIImageView *)subsubView);
[imageView removeFromSuperview];
}else if ([subsubView class] == [UILabel class]) {
UILabel *labelView = ((UILabel *)subsubView);
[labelView removeFromSuperview];
}
}
}
}
- (void)animateCalloutAppearance:(BOOL)inAdd {
if (inAdd == YES) {
self.rightCalloutAccessoryView.hidden = NO;
[UIView animateWithDuration:0.4 delay:0 options: UIViewAnimationOptionTransitionNone
animations:^{
self.calloutView.frame = CGRectMake(self.calloutView.frame.origin.x
, self.calloutView.frame.origin.y
, self.calloutView.frame.size.width+150
, self.calloutView.frame.size.height);
self.rightCalloutAccessoryView.alpha = 1;
self.rightCalloutAccessoryView.frame = CGRectMake(self.calloutView.frame.size.width - (self.rightCalloutAccessoryView.frame.size.width)
, self.rightCalloutAccessoryView.frame.origin.y
, self.rightCalloutAccessoryView.frame.size.width
, self.rightCalloutAccessoryView.frame.size.height);
} completion:^(BOOL finished){ }];
} else {
[UIView animateWithDuration:0.4 delay:0 options: UIViewAnimationOptionTransitionNone
animations:^{
self.rightCalloutAccessoryView.alpha = 0;
self.rightCalloutAccessoryView.frame = CGRectMake(0
, self.rightCalloutAccessoryView.frame.origin.y
, self.rightCalloutAccessoryView.frame.size.width
, self.rightCalloutAccessoryView.frame.size.height);
self.calloutView.frame = CGRectMake(self.calloutView.frame.origin.x
, self.calloutView.frame.origin.y
, self.calloutView.frame.size.width-150
, self.calloutView.frame.size.height);
} completion:^(BOOL finished){
self.image = [UIImage imageNamed:#"map_pin.png"];
[self.calloutView removeFromSuperview];
[self.rightCalloutAccessoryView removeFromSuperview];
}];
}
}
#end
Your annotation class needs to have a subtitle attribute, yours has subTitle.
If calloutAccessoryControlTapped is not being called it is usually a sign your MKMapview's delegate has not been set. However you're only setting the accessory button when it gets selected. Do you have a good reason for that? Since the callout window won't be visible until it is selected, I would advise you to set the accessory button in viewForAnnotation and let it appear when the callout window does.
I fix the first one:
TAPPMapAnnotation *theAnnotation = (TAPPMapAnnotation *)self.annotation;
self.title = [[UILabel alloc]init];
self.title.font = [UIFont systemFontOfSize:12.0];
self.title.textColor = [UIColor whiteColor];
self.title.backgroundColor = [UIColor clearColor];
self.title.text = theAnnotation.title;
[...]
[self.theView addSubview:self.title];

accessing unknown 'flipDelegate' component of a property

Hi when I am compiling my code i am getting this error-"accessing unknown 'flipDelegate' component of a property"
this is the code from where i am getting error-
//
// RootViewController.m
// Dolphia
//
// Created by Dolphia Nandi on 4/3/11.
// Copyright 2011 State University of New York at Buffalo. All rights reserved.
//
#import "RootViewController.h"
#import "MainViewController.h"
#import "FlipSideViewController.h"
#implementation RootViewController
#synthesize mainViewController;
#synthesize flipSideViewController;
- (void)loadMainViewController {
MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.mainViewController = viewController;
self.mainViewController.flipDelegate = self;
[viewController release];
}
- (void)loadFlipSideViewController {
FlipSideViewController *viewController = [[FlipSideViewController alloc] initWithNibName:#"FlipSideViewController" bundle:nil];
self.flipSideViewController = viewController;
self.flipSideViewController.flipDelegate = self;
[viewController release];
}
- (void)viewDidLoad {
[self loadMainViewController]; // Don't load the flipside view unless / until necessary
[self.view addSubview:mainViewController.view];
}
// This method is called when either of the subviews send a delegate message to us.
// It flips the displayed view from the whoever sent the message to the other.
- (void)toggleView:(id)sender {
if (flipSideViewController == nil) {
[self loadFlipSideViewController];
}
UIView *mainWindow = mainViewController.view;
UIView *flipSideView = flipSideViewController.view;
/*[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
if(flipeffect >= 0 && flipeffect < 2) {
flipeffect++;
[UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES];
} else if (flipeffect >= 2 && flipeffect < 4) {
flipeffect++;
[UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionCurlUp : UIViewAnimationTransitionCurlDown) forView:self.view cache:YES];
} else if (flipeffect >= 4 && flipeffect < 6) {
flipeffect++;
[UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.view cache:YES];
} else {
flipeffect++;
if(flipeffect > 7)
flipeffect = 0;
[UIView setAnimationTransition:((voiceViewController == sender) ? UIViewAnimationTransitionCurlDown : UIViewAnimationTransitionCurlUp) forView:self.view cache:YES];
}*/
if (mainViewController == sender) {
[flipSideViewController viewWillAppear:YES];
[mainViewController viewWillDisappear:YES];
[mainWindow removeFromSuperview];
[self.view addSubview:flipSideView];
[mainViewController viewDidDisappear:YES];
[flipSideViewController viewDidAppear:YES];
} else {
[mainViewController viewWillAppear:YES];
[flipSideViewController viewWillDisappear:YES];
[flipSideView removeFromSuperview];
[self.view addSubview:mainWindow];
[flipSideViewController viewDidDisappear:YES];
[mainViewController viewDidAppear:YES];
}
//[UIView commitAnimations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[mainViewController release];
[flipSideViewController release];
[super dealloc];
}
#end
Both mainViewController and flipSideViewController should have flipDelegate as instance variable and make sure you add #synthesize and #property

Memory Management on NSMutableArray

I read some materials about this then I tried to wrote a simple
app but got confused, here is the sample (using cocos2d template):
MySpriteObject class:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface MySpriteObject : CCNode {
CCSprite *mySprite;
NSString *spriteInfo;
}
#property(nonatomic,retain) CCSprite *mySprite;
#property(nonatomic,retain) NSString *spriteInfo;
#end
#import "MySpriteObject.h"
#implementation MySpriteObject
#synthesize mySprite;
#synthesize spriteInfo;
-(id) init
{
NSLog(#"MySpriteObject init");
if ((self = [super init])) {
self.mySprite = [CCSprite spriteWithFile:#"Icon.png"];
self.spriteInfo = [[[NSString alloc] initWithFormat:#"sprite info"] autorelease];
}
return (self);
}
-(void)dealloc
{
NSLog(#"MySpriteObject dealloc");
[self.spriteInfo release];
[super dealloc];
}
#end
MyObjectManager class:
#import "cocos2d.h"
#import "MySpriteObject.h"
#class MySpriteObject;
#interface MyObjectManager : CCNode {
}
+(MyObjectManager *)sharedMyObjectManager;
-(NSMutableArray *)func1;
-(NSMutableArray *)func2;
#end
#import "MyObjectManager.h"
#import "MySpriteObject.h"
#implementation MyObjectManager
static MyObjectManager *_sharedMyObjectManager = nil;
+(MyObjectManager *)sharedMyObjectManager
{
NSLog(#"MyObjectManager sharedMyObjectManager");
if (!_sharedMyObjectManager) {
if( [ [MyObjectManager class] isEqual:[self class]] )
_sharedMyObjectManager = [[MyObjectManager alloc] init];
else
_sharedMyObjectManager = [[self alloc] init];
}
return _sharedMyObjectManager;
}
-(id)init
{
NSLog(#"MyObjectManager init");
if( (self = [super init]) ) {
}
return self;
}
-(void)dealloc
{
NSLog(#"MyObjectManager dealloc");
[super dealloc];
}
-(NSMutableArray *)func1
{
NSMutableArray *array1 = [[NSMutableArray alloc] init];
array1 = [self func2];
return array1;
}
-(NSMutableArray *)func2;
{
NSMutableArray *array2 = [[NSMutableArray alloc] init];
for (int i = 0; i < 3; i++) {
MySpriteObject *mySpriteObject = [[MySpriteObject alloc] init];
[array2 addObject:mySpriteObject];
//[mySpriteObject release];
}
return array2;
}
#end
And in the "HelloWorldScene.m" init method:
-(id) init
{
if( (self=[super init] )) {
NSMutableArray *array = [[NSMutableArray alloc] init];
array = [[MyObjectManager sharedMyObjectManager] func1];
for (int i = 0; i < array.count; i++) {
MySpriteObject *s = [[MySpriteObject alloc] init];
s = [array objectAtIndex:i];
NSLog(#"%#", s.spriteInfo);
[s release];
}
[array release];
}
return self;
}
The code posted above works fine (at least no crash), but I think there is
memory leak out there.
At first, I had the fun1 fun2 method return the array like this:
return [array1 autorelease];
return [array2 autorelease];
And released the SpriteObject in the func2 methoed as you can see the commented line.
But the app crashed.
Then I uncommented the SpriteObject release line but it still crashed.
Then I deleted the two autorelease in the return statement and it worked
fine.
Can somebody give something suggestion according to the code above???
Thanks in advance.
Oh boy, there are multiple problems. At first remember to release everything you called "alloc, new, retain, copy" upon. See Objective C release, autorelease, and data types and Release, Dealloc, and the Self reference
The basic problem here is, that you are overwriting previously created variables. For example:
NSMutableArray *array = [[NSMutableArray alloc] init];
array = ... ;
[array release];
Therefore you create a memory leak and get double release trouble. See obj-c NSString and alloc / retain / release for how to do it right.

Resources