Obj-C UIActionSheet Memory Leaks iPhone - iphone

I'm coding a popup screen that will show up if a the value for mulValue in the settings is nil. Here is the code:
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize myHelpfile = ivHelpfile; //UIAlertView
#synthesize myAboutfile = ivAboutfile; //UIAlertView
#synthesize myNoarea = ivNoarea; //UIAlertView
#synthesize myMap = ivMap; //UIImageView
#synthesize myAreapick = ivAreapick; //UIActionSheet
#synthesize myAdvancedmode = ivAdvancedmode; //NSString
#synthesize myAreaset = ivAreaset; //NSString
#synthesize myAreaarray = ivAreaarray; //NSArray
#synthesize appSettingsViewController, settingsViewController;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Wildlife";
NSString *area = [[NSUserDefaults standardUserDefaults] stringForKey:#"mulValue"];
[self setMyAreaset:area];
if ([self myAreaset] == nil) { //check if any region is selected. If not, push UIActionsheet
NSArray *array = [[NSArray alloc] initWithObjects: // creating array for different regions
[NSString stringWithString:#"Region 1"],
[NSString stringWithString:#"Region 2"],
[NSString stringWithString:#"Region 3"],
[NSString stringWithString:#"Region 4"],
[NSString stringWithString:#"Region 5"],
[NSString stringWithString:#"Region 6"],nil];
[self setMyAreaarray:array];
[array release], array = nil;
NSLog(#"Built areaselectArray");
NSLog(#"Values of areaselectArray are %#",[self myAreaarray]);
UIActionSheet *areaselect = [[UIActionSheet alloc] initWithTitle:#"Select your current area" //creation of popup Area Selection
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[self setMyAreapick:areaselect];
[areaselect release], areaselect = nil;
int countarray = [[self myAreaarray] count];
for (int i = 0; i < countarray; i++) { //building list from array
[[self myAreapick] addButtonWithTitle:[[self myAreaarray] objectAtIndex:i]];
}
[[self myAreapick] addButtonWithTitle:#"Cancel"];
[self myAreapick].cancelButtonIndex = countarray;
[[self myAreapick] showInView:self.view];//show the general UIActionSheet instance
NSLog(#"Out of viewDidLoad");
}
else {
NSLog(#"Area is %#, no need for areaselectArray",area);
}
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger )buttonIndex
{
int countarray = [[self myAreaarray] count];
if (buttonIndex != countarray) { //cancel button is at countarray, so for anything that is not cancel, do:
NSString *area = [[self myAreaarray] objectAtIndex:(buttonIndex)];
[self setMyAreaset:area];
[[NSUserDefaults standardUserDefaults] setObject:[self myAreaset] forKey:#"mulValue"];
[[NSUserDefaults standardUserDefaults] synchronize]; //sync
NSLog(#"Released areaselectArray");
}
else {
}
}
And in my FirstViewController.h I have:
#interface FirstViewController : UIViewController <UIActionSheetDelegate, IASKSettingsDelegate, UIAlertViewDelegate> {
UIAlertView *ivHelpfile;
UIAlertView *ivAboutfile;
UIAlertView *ivNoarea;
UIActionSheet *ivAreapick;
UIImageView *ivMap;
NSString *ivAdvancedmode;
NSString *ivAreaset;
NSArray *ivAreaarray;
}
#property(nonatomic, retain) UIAlertView *myHelpfile;
#property(nonatomic, retain) UIAlertView *myAboutfile;
#property(nonatomic, retain) UIAlertView *myNoarea;
#property(nonatomic, retain) UIActionSheet *myAreapick;
#property(nonatomic, retain) UIImageView *myMap;
#property(nonatomic, copy) NSString *myAdvancedmode;
#property(nonatomic, copy) NSString *myAreaset;
#property(nonatomic, retain) NSArray *myAreaarray;
When I run my app in the simulator with Instruments running, I get a memory leak whenever I scroll the list of rows (as built by [self myAreaarray]) and release my finger. The weird thing is, it has not really done anything else at that point. The main view is loaded, but it would be strange that that would cause a memory leak based on scrolling through the list.
The leaks I get in Instruments are the following:
_NSCFType 48 bytes CoreGraphics CGTypeCreateInstanceWithAllocator
UIDeviceWhiteColor 16 bytes UIKit +[UIColor allocWithZone:]
When I scroll through the list again, more of those errors show up. It looks like I'm allocating something and not releasing it (while I'm scrolling the list?), but I can't find it at this point.
Any help would be appreciated!

I'm seeing it as well, even abstracting all your app code from it:
UIActionSheet *as = [[UIActionSheet alloc] initWithTitle:#"Test" delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
for (int i = 0; i < 100; i++) {
[as addButtonWithTitle:[NSString stringWithFormat:#"Button %i", i]];
}
as.cancelButtonIndex = 99;
as.destructiveButtonIndex = 0;
[as showInView:self.view];
[as release];
When running through Instruments memory leak profiler, each display of the action sheet yieds 6 UIDeviceWhiteColor leaks and 4 CGColor leaks. Looks to me like this is a bug in UIKit.

Related

To show A FirstViewController On Call of a method from SecondViewController in Iphone

Actually I am Making an Alarm app. In that When i set the Time The UILocalNotification event happens at that time and it calls the method of AppDelegate class i.e didReceiveNotifications method. In this method i have written a code to call a method of SetViewController (showReminder method) and now in this method i want that it should show a NewViewController i.e TimeViewController as i have to show animation when the Alarm Invokes.
I need this as When Alarm invokes i have setted a Action sheet to appear but i wanted to show animation also.Action sheet appears in all views But the animation can be Shown in only particular view, that's why i need to show A different ViewController.
Here is the code for what i am trying :-
I have tried al these also like PresentModalViewController, dismissModalViewController, AddSubview, remove superView... but result are negative :( what should i do..?
Almost Whole CODE:--
AppDelegate Class :-
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
if (notification){
NSLog(#"In did Notification");
NSString *reminderText = [notification.userInfo objectForKey:kRemindMeNotificationDataKey];
[viewController showReminder:reminderText];
application.applicationIconBadgeNumber = 0;
}
}
setViewController.h :-
#interface SetAlarmViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate,UIActionSheetDelegate>{
IBOutlet UITableView *tableview;
IBOutlet UIDatePicker *datePicker;
IBOutlet UITextField *eventText;
TPKeyboardAvoidingScrollView *scrollView;
IBOutlet UINavigationBar *titleBar;
IBOutlet UIButton *setAlarmButton;
AVAudioPlayer *player;
int index;
The420DudeAppDelegate *appDelegate;
TimeViewController *viewController;
IBOutlet UIImageView *animatedImages;
NSMutableArray *imageArray;
AVPlayerItem *player1,*player3;
AVPlayerItem *player2,*player4;
AVQueuePlayer *queuePlayer;
}
#property (nonatomic, retain) IBOutlet UIImageView *animatedImages;
#property (nonatomic, retain) IBOutlet UITableView *tableview;
#property (nonatomic, retain) IBOutlet UIDatePicker *datePicker;
#property (nonatomic, retain) IBOutlet UITextField *eventText;
#property (nonatomic, retain) TPKeyboardAvoidingScrollView *scrollView;
#property(nonatomic, retain) IBOutlet UINavigationBar *titleBar;
#property(nonatomic, retain) IBOutlet UIButton *setAlarmButton;
#property(nonatomic) UIReturnKeyType returnKeyType;
#property(nonatomic, retain) IBOutlet TimeViewController *viewController;
- (IBAction) scheduleAlarm:(id)sender;
- (void)showReminder:(NSString *)text;
-(IBAction)onTapHome;
-(IBAction)onTapChange:(id)sender;
#end
SetViewController.m :-
#synthesize datePicker,tableview, eventText,titleBar,setAlarmButton,returnKeyType,scrollView,animatedImages,viewController;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (The420DudeAppDelegate *)[[UIApplication sharedApplication] delegate];
eventText.returnKeyType = UIReturnKeyDone;
viewController = [[TimeViewController alloc] initWithNibName:#"TimeViewController" bundle:nil];
NSDate *now = [NSDate date];
[datePicker setDate:now animated:YES];
eventText.delegate = self;
index = 0;
NSString *path1 = [[NSBundle mainBundle] pathForResource:#"inhale" ofType:#"mp3"];
NSURL *url1 = [NSURL fileURLWithPath:path1];
player1 = [[AVPlayerItem alloc]initWithURL:url1];
NSString *path3 = [[NSBundle mainBundle] pathForResource:#"sound1" ofType:#"wav"];
NSURL *url3 = [NSURL fileURLWithPath:path3];
player3 = [[AVPlayerItem alloc]initWithURL:url3];
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"exhale" ofType:#"mp3"];
NSURL *url2 = [NSURL fileURLWithPath:path2];
player2 = [[AVPlayerItem alloc]initWithURL:url2];
NSString *path4 = [[NSBundle mainBundle] pathForResource:#"Dude" ofType:#"mp3"];
NSURL *url4 = [NSURL fileURLWithPath:path4];
player4 = [[AVPlayerItem alloc]initWithURL:url4];
NSArray *items = [[NSArray alloc]initWithObjects:player1,player3,player2,player4,nil];
queuePlayer = [[AVQueuePlayer alloc] initWithItems:items];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playEnded) name:AVPlayerItemDidPlayToEndTimeNotification object:player4];
}
-(void)onAlarmInvoke
{
animatedImages = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
animatedImages.userInteractionEnabled = YES;
[animatedImages setContentMode:UIViewContentModeScaleToFill];
[self.view addSubview : animatedImages];
[queuePlayer play];
// Array to hold jpg images
imageArray = [[NSMutableArray alloc] initWithCapacity:IMAGE_COUNT];
// Build array of images, cycling through image names
for (int i = 1; i <= IMAGE_COUNT; i++)
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"animation(%d).jpg", i]]];
animatedImages.animationImages = [NSArray arrayWithArray:imageArray];
// One cycle through all the images takes 1.0 seconds
animatedImages.animationDuration = 12.0;
// Repeat foreverlight electro / 4 sec.
animatedImages.animationRepeatCount = -1;
// Add subview and make window visible
// [self.view addSubview:animatedImages];
animatedImages.image = [imageArray objectAtIndex:imageArray.count - 1];
// Start it up
[animatedImages startAnimating];
// Wait 5 seconds, then stop animation
[self performSelector:#selector(stopAnimation) withObject:nil afterDelay:15000];
}
-(void)playEnded
{
[self performSelector:#selector(playNextItem) withObject:nil afterDelay:5.0];
}
-(void)playNextItem
{
[queuePlayer play];
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[scrollView adjustOffsetToIdealIfNeeded];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
[self.tableview reloadData];
}
- (IBAction) scheduleAlarm:(id)sender {
[eventText resignFirstResponder];
// Get the current date
NSDate *pickerDate = [self.datePicker date];
// NSDate *selectedDate = [datePicker date]; // you don't need to alloc-init the variable first
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *dc = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:pickerDate];
pickerDate = [cal dateFromComponents:dc];
NSLog(#"%# is the date in picker date",pickerDate);
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = pickerDate;
// NSLog(#"%#",localNotif.fireDate);
localNotif.timeZone = [NSTimeZone defaultTimeZone];
// NSLog(#"%#",localNotif.timeZone);
// Notification details
localNotif.alertBody = [eventText text];
// Set the action button
localNotif.alertAction = #"Show me";
localNotif.repeatInterval = NSDayCalendarUnit;
localNotif.soundName = #"jet.wav";
// Specify custom data for the notification
NSDictionary *userDict = [NSDictionary dictionaryWithObject:eventText.text
forKey:kRemindMeNotificationDataKey];
localNotif.userInfo = userDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release];
[self.tableview reloadData];
eventText.text = #"";
viewController = [[TimeViewController alloc] initWithNibName:#"TimeViewController" bundle:nil];
[self presentModalViewController:viewController animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
index = indexPath.row;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Warning!!!"
message:#"Are you sure you want to Delete???" delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok",nil];
[alertView show];
[alertView release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *notify = [notificationArray objectAtIndex:index];
if(buttonIndex == 0)
{
// Do Nothing on Tapping Cancel...
}
if(buttonIndex ==1)
{
if(notify)
[[UIApplication sharedApplication] cancelLocalNotification:notify];
}
[self.tableview reloadData];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *notif = [notificationArray objectAtIndex:indexPath.row];
[cell.textLabel setText:notif.alertBody];
[cell.detailTextLabel setText:[notif.fireDate description]];
return cell;
}
- (void)viewDidUnload {
datePicker = nil;
tableview = nil;
eventText = nil;
[self setScrollView:nil];
[super viewDidUnload];
}
- (void)showReminder:(NSString *)text {
[self onAlarmInvoke];
[self.view addSubview:viewController.view];
UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:#"Cancel" otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect rect = self.view.frame;
// if(rect.origin.y <= 480)
// rect.origin.y +=20;
self.view.frame = rect;
[actionSheet showInView:self.view];
[actionSheet release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
[player stop];
NSLog(#"OK Tapped");
}
if(buttonIndex == 1)
{
[player stop];
NSLog(#"Cancel Tapped");
}
}
-(IBAction)onTapHome{
viewController = [[TimeViewController alloc] initWithNibName:#"TimeViewController" bundle:nil];
[self presentModalViewController:viewController animated:YES];
}
- (void)dealloc {
[super dealloc];
[datePicker release];
[tableview release];
[eventText release];
[scrollView release];
}
-(IBAction)onTapChange:(id)sender{
SetTimeViewController *viewC = [[SetTimeViewController alloc]initWithNibName:#"SetTimeViewController" bundle:nil];
[self presentModalViewController:viewC animated:YES];
}
#end
Your viewController is probably showing the view, but without the SetViewController's view on the screen you can't see it. Your going to have to first go to the SetViewController and then present your TimeViewController. Is this right, you want to show the SetViewController but call the showReminder: method right away? But only from the didReceiveLocalNotification:.
If this is the case, set a flag,and a text property in your SetViewControllers .h,
BOOL isFromNotification;
NSString *notifText;
and present the SetViewController,and set the flag
SetViewController *setViewController = [SetViewController alloc]........
setViewController.isFromNotification = YES;
setViewController.notifText = reminderText;
[self presentModalViewController animated:YES}
and then in the viewDidAppear: of SetViewController
if(isFromNotification = YES){
[self showReminders:notifText];
}
If I got you right ,
upon notification you would like to show animation on a new view and then show the action sheet ?
Right now you call from appdelegate
[viewController showReminder:reminderText];
which by the way should be self.viewcontroller or _viewcontroller for the actually retained object
In showreminder you call
animation, which in itself adds a subview and by the way is running in the same thread , ie in serial.
and then you add the viewcontroller again as a subview.
and then you try to add the actionsheet from parent to the subview(viewcontroller), when actionsheet should probably be in the viewcontroller itself.
Did i get that right ?
No sure really whats breaking down, could be on several areas, as pointed out above.
I would :
make sure you call the retained objects through valid pointers ( using self for instance)
have a viewcontroller that you present modal as a subview that show animations on a separate thread (performselectoronthread) and have the actionsheet on that.
Then if you need to call the parent, you setup a delegate or you do the ugly way.
self.yourviewcontroller.myParentObj = self
ie set a yourviewcontroller pointer on the sub viewcontroller, which you can then openly call like
[self.myParentObj whatevermethod_you_have_in_parent];
But then again I write this from top of my head..

wanted to play my sound file when notification event occurs and then stop

I am making an Alarm clock in which i want that when the selected time through Datepicker occur instead of only notification and Badge occurance , I wanted to play my custom Sound file i.e. jet.wav (it is of less than 30 sec and in .wav format).i want that as soon as my notification occurs it should play a sound and when i click on the app or alert view then it should stop. So can anyone please help me out. here is what i am trying :-
Code:-
#class The420DudeViewController;
#interface The420DudeAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
The420DudeViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet The420DudeViewController *viewController;
extern NSString *kRemindMeNotificationDataKey;
#implementation The420DudeAppDelegate
#synthesize window;
#synthesize viewController;
NSString *kRemindMeNotificationDataKey = #"kRemindMeNotificationDataKey";
#pragma mark -
#pragma mark === Application Delegate Methods ===
#pragma mark -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Class cls = NSClassFromString(#"UILocalNotification");
if (cls) {
UILocalNotification *notification = [launchOptions objectForKey:
UIApplicationLaunchOptionsLocalNotificationKey];
if (notification) {
NSString *reminderText = [notification.userInfo
objectForKey:kRemindMeNotificationDataKey];
[viewController showReminder:reminderText];
}
}
application.applicationIconBadgeNumber = 0;
[window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
application.applicationIconBadgeNumber = 0;
}
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
application.applicationIconBadgeNumber = 0;
NSString *reminderText = [notification.userInfo
objectForKey:kRemindMeNotificationDataKey];
[viewController showReminder:reminderText];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
#interface The420DudeViewController : UIViewController {
IBOutlet UINavigationBar *titleBar;
IBOutlet UIButton *setAlarmButton;
IBOutlet UIDatePicker *selectTimePicker;
AVAudioPlayer *player;
}
#property(nonatomic, retain) IBOutlet UINavigationBar *titleBar;
#property(nonatomic, retain) IBOutlet UIButton *setAlarmButton;
#property(nonatomic, retain) IBOutlet UIDatePicker *selectTimePicker;
-(IBAction)onTapSetAlarm;
- (void)showReminder:(NSString *)text;
#end
#implementation The420DudeViewController
#synthesize titleBar,setAlarmButton,selectTimePicker;
#pragma mark -
#pragma mark === Initialization and shutdown ===
#pragma mark -
- (void)viewDidLoad {
[super viewDidLoad];
selectTimePicker.minimumDate = [NSDate date];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.setAlarmButton = nil;
self.selectTimePicker = nil;
}
/*
-(void)viewWillAppear:(BOOL)animated
{
NSString *path = [[NSBundle mainBundle]pathForResource:#"Song1" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
// [player play];
}
*/
-(IBAction)onTapSetAlarm
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.fireDate = [selectTimePicker date];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = #"Did you forget something?";
notif.alertAction = #"Show me";
notif.repeatInterval = NSDayCalendarUnit;
// notif.soundName = UILocalNotificationDefaultSoundName;
notif.soundName = [[NSBundle mainBundle]pathForResource:#"jet" ofType:#"wav"];
notif.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"Mayank"
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
}
/*
NSDateFormatter *timeFormat = [[NSDateFormatter alloc] init];
[timeFormat setDateFormat:#"HH:mm a"];
NSDate *selectedDate = [[NSDate alloc] init];
selectedDate = [selectTimePicker date];
NSString *theTime = [timeFormat stringFromDate:selectedDate];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Time selected" message:theTime delegate:nil cancelButtonTitle:#"YES" otherButtonTitles:nil];
[alert show];
[alert release];
// [timeFormat release];
// [selectedDate release];
*/
}
#pragma mark -
#pragma mark === Public Methods ===
#pragma mark -
- (void)showReminder:(NSString *)text {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Reminder"
message:#" TEXT " delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
- (void)dealloc {
[super dealloc];
[titleBar release];
[setAlarmButton release];
[selectTimePicker release];
}
#end
According to the documentation for soundName, you should
specify the filename (including extension) of a sound resource in the application’s main bundle
Thus I suggest you change this line of -[The420DudeViewController onTapSetAlarm]:
notif.soundName = [[NSBundle mainBundle]pathForResource:#"jet" ofType:#"wav"];
to the following:
notif.soundName = #"jet.wav";

My object seems to get deleted, with me requesting that. EXEC_BAD_ACCESS

I create an array of custom objects called players.
#interface Player : NSObject
{
NSString *name;
NSNumber *spd;
NSNumber *atk;
NSNumber *def;
}
#property(nonatomic, retain) NSString *name;
#property(nonatomic, retain) NSNumber *spd;
#property(nonatomic, retain) NSNumber *atk;
#property(nonatomic, retain) NSNumber *def;
#end
#import "Player.h"
#implementation Player
#synthesize name;
#synthesize spd;
#synthesize atk;
#synthesize def;
#end
That seems ok.
So I have a function that setups an array full of Player objects.
-(void) initTheGame
{
NSLog(#" initTheGame");
playerArray =[[NSMutableArray alloc] init];
p1Cards =[[NSMutableArray alloc] init];
p2Cards =[[NSMutableArray alloc] init];
for (int i = 0; i < 20; i++)
{
Player *myPlayer = [[Player alloc] init];
myPlayer.name =[NSString stringWithFormat:#"Name%d", (rand()%99)];
myPlayer.spd = [NSNumber numberWithInteger:(rand() % 100)];
myPlayer.atk = [NSNumber numberWithInteger:(rand() % 100)];
myPlayer.def = [NSNumber numberWithInteger:(rand() % 100)];
[playerArray addObject:myPlayer];
[myPlayer autorelease];
}
[self dealHands];
[self setupValuesForUI];
}
It works as expected. Fills up the array full of Player objects containing random data.
-(void) setupValuesForUI
{
NSLog(#"setupValuesForUI");
Player *p1 = [[Player alloc] init];
p1 = [playerArray objectAtIndex:0];
p1Name.text = p1.name;
[p1Speed setTitle:[NSString stringWithFormat:#"Spd: %#",[p1.spd stringValue] ] forState:UIControlStateNormal];
[p1Attack setTitle:[NSString stringWithFormat:#"Atk: %#",[p1.atk stringValue] ] forState:UIControlStateNormal];
[p1Defense setTitle:[NSString stringWithFormat:#"Def: %#",[p1.def stringValue] ] forState:UIControlStateNormal];
[p1 autorelease];
}
This function uses some IBOutlets to set the Text values for a Lable and 3 Buttons. All work ok they display there data.
Now when i press a button and an IBAction method gets called my app crashes out with an
EXEC_BAD_ACCESS
The code hasnt changed, I try and access the object in the same way, but it seems to have disappeared. :(
Can somebody explain what I did wrong. I'm a newbie to Objective C so forgive me if this is
an obvious problem to you. I can find it after hours of trying to debug it.
-(IBAction) spd
{
Player *p1 = [[Player alloc] init];
p1 = [playerArray objectAtIndex:0];
int x = [p1.spd integerValue]; // this line crashes out the app
}
You need to remove the [p1 autorelease]; from the setupValuesForUI function. Since you did not alloc or retain it in this method, then there is no need to release it.
PS. you should use [myPlayer release]; and not [myPlayer autorelease]; in initTheGame just as a better coding practice.
This place has errors.
-(void) setupValuesForUI
{
NSLog(#"setupValuesForUI");
Player *p1 = [[Player alloc] init];
p1 = [playerArray objectAtIndex:0];
....
[p1 autorelease];
}

Initialization problem

I have a problem.
This is my code.
When i try to use the IBAction SavePosition the "arrayPosition" isn't update.
Else if i initialize the "arrayPosition" in "SavePosition" the value is stored in the array.
Why this anomaly?
#import <UIKit/UIKit.h>
#interface AccelerometroViewController : UIViewController <UIAccelerometerDelegate, UITextFieldDelegate, UIAlertViewDelegate>{
//.....
NSMutableArray *arrayPosizioni;
NSMutableArray *arrayPosizioniCorrenti;
NSString *nomePosizioneCorrente;
}
-(IBAction)salvaPosizione;
//...
#property (nonatomic, assign) NSMutableArray *arrayPosizioni;
#property (nonatomic, assign) NSMutableArray *arrayPosizioniCorrenti;
#property (nonatomic, assign) NSString *nomePosizioneCorrente;
#end
#import "AccelerometroViewController.h"
#import "Position.h"
#implementation AccelerometroViewController
float actualX;
float actualY;
float actualZ;
#synthesize arrayPosition;
#synthesize arrayCurrentPosition;
#synthesize nameCurrentPosition;
-(id)init {
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayCurrentPosition = [[NSMutableArray alloc]init];
nameCurrentPosition = [NSString stringWithFormat:#"noPosition"];
actualX = 0;
actualY = 0;
actualZ = 0;
}
return self;
}
-(void)updateTextView:(NSString*)nomePosizione
{
NSString *string = [NSString stringWithFormat:#"%#", nameCurrentPosition];
textEvent.text = [textEvent.text stringByAppendingString:#"\n"];
textEvent.text = [textEvent.text stringByAppendingString:string];
}
-(IBAction)savePosition{
Posizione *newPosition;
newPosition = [[Position alloc]init];
if([newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]){
//setValue is a method of Position. I'm sure that this method is correct
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio Posizione" message:#"Posizione salvata con successo" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[arrayPosition addObject:newPosition];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio osizione" message:#"Errore nel salvataggio" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Whats going on?
I bet you're creating your view controller inside a xib file?
If you set a breakpoint inside your init method on the line
arrayPosition = [[NSMutableArray alloc]init];
I bet it never runs. This means that when you get to the line
[arrayPosition addObject:newPosition];
arrayPosition is still nil so nothing happens.
How to fix it?
If you're initializing a UIViewController it's either called inside initWithNibName:bundle: if you've created it in code or in initWithCoder: if it's created inside a xib file.
You need to do something like this :
- (void) initialise {
arrayPosition = [[NSMutableArray alloc] init];
arrayCurrentPosition = [[NSMutableArray alloc] init];
nameCurrentPosition = #"noPosition";
actualX = 0;
actualY = 0;
actualZ = 0;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:bundle]) {
[self initialise];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder:decoder]) {
[self initialise];
}
return self;
}
This will call initailise regardless of how the view controller is created.
This:
[newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]
... is gibberish. I don't even see how it compiles. I assume its a typo. However, if the function does not return a boolean it will return a void pointer and always evaluate to false so the block is never called.
More generally, your problem is most likely that you are not using the self.propertyName notation to refer to your properties so they are not being retained. E.g.
[arrayPosition addObject:newPosition];
should be:
[self.arrayPosition addObject:newPosition];
... as should all other references to arrayPosition in the code.

initialization with a nibFIle failed

I have a problem.
I try to initialize a variabile in a classViewController created inside a xib file.
I try with the code below but when i append a object to array, these array isn't initialized.
Can you help me?
thanks and sorry for my english.
#import <UIKit/UIKit.h>
#interface AccelerometroViewController : UIViewController <UIAccelerometerDelegate, UITextFieldDelegate, UIAlertViewDelegate>{
//.....
NSMutableArray *arrayPosizioni;
NSMutableArray *arrayPosizioniCorrenti;
NSString *nomePosizioneCorrente;
}
-(IBAction)salvaPosizione;
//...
#property (nonatomic, assign) NSMutableArray *arrayPosizioni;
#property (nonatomic, assign) NSMutableArray *arrayPosizioniCorrenti;
#property (nonatomic, assign) NSString *nomePosizioneCorrente;
#end
#import "AccelerometroViewController.h"
#import "Position.h"
#implementation AccelerometroViewController
float actualX;
float actualY;
float actualZ;
#synthesize arrayPosition;
#synthesize arrayCurrentPosition;
#synthesize nameCurrentPosition;
-(id)init {
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayCurrentPosition = [[NSMutableArray alloc]init];
nameCurrentPosition = [NSString stringWithFormat:#"noPosition"];
actualX = 0;
actualY = 0;
actualZ = 0;
}
return self;
}
-(void)updateTextView:(NSString*)nomePosizione
{
NSString *string = [NSString stringWithFormat:#"%#", nameCurrentPosition];
textEvent.text = [textEvent.text stringByAppendingString:#"\n"];
textEvent.text = [textEvent.text stringByAppendingString:string];
}
-(IBAction)savePosition{
Posizione *newPosition;
newPosition = [[Position alloc]init];
if([newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]){
//setValue is a method of Position. I'm sure that this method is correct
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio Posizione" message:#"Posizione salvata con successo" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[arrayPosition addObject:newPosition];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio osizione" message:#"Errore nel salvataggio" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void) initialise {
arrayPosition = [[NSMutableArray alloc] init];
arrayCurrentPosition = [[NSMutableArray alloc] init];
nameCurrentPosition = #"noPosition";
actualX = 0;
actualY = 0;
actualZ = 0;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:bundle]) {
[self initialise];
}
}
In addition to Felix's comment regarding the mis-naming, your properties are wrong too. Objects need to be retained or copied, not assigned (in most cases) so that you're certain their value won't go away. You need to have ownership of them. As such I would use the following:
#property (nonatomic, readwrite, retain) NSMutableArray *arrayPosition;
#property (nonatomic, readwrite, retain) NSMutableArray *arrayCurrentPosition;
#property (nonatomic, readwrite, copy) NSString *nameCurrentPosition;
Then, since you've retained something you're responsible for releasing it. As such you'll need a dealloc method to do that.
-(void)dealloc {
self.arrayPosition = nil;
self.arrayCurrentPosition = nil;
self.nameCurrentPosition = nil;
[super dealloc];
}