Data I need to displayed has been stored into a temp file.When I execute the application, NSLog can receive the data, but UITextField didn't respond. I don't know if I am using the correct syntax. And I am not sure why it doesn't work...
Update: I tried to assign a value to UItextField, but the UItextField doesn't display it neither
-(void)readFilewin
{
// ....
NSString *pathsWin;
NSArray *pathsWin1= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
pathsWin = [[pathsWin1 objectAtIndex:0] stringByAppendingPathComponent:#"arraycountwin.plist"];
NSArray *getfile = [NSArray arrayWithContentsOfFile:pathsWin];
//NSArray *getfile = [NSArray arrayWithContentsOfFile:#"arraycountwin.plist"];
//self.TotalWinTextField.text = [getfile objectAtIndex:0];
NSString * win = [[NSString alloc]init];
win = [getfile objectAtIndex:0];
NSLog(#"Win : %#", win);
self.TotalWinTextField.text = [NSString stringWithFormat:#"%#", win];
}
-(void)readFileLoss{...}
-(void)readFilestats
{
// ....
NSString *statspath;
NSArray *statspaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
statspath = [[statspaths objectAtIndex:0] stringByAppendingPathComponent:#"arraystats.plist"];
NSArray *getfile = [NSArray arrayWithContentsOfFile:statspath];
NSString * time = [[NSString alloc]init];
time = [getfile objectAtIndex:0];
NSLog(#"Time : %#", time);
NSString * time1 = [[NSString alloc]init];
time1 = [getfile objectAtIndex:1];
NSLog(#"Time1 : %#", time1);
self.textField1.text = time; //broke here after update the viewDidLoad as #paul11 advise
self.textField2.text = time1;
}
Update for testing purpose to make sure the textfield is working, but it cannot even read the assigned value:
- (void)readFilewin
{
self.TotalWinTextField.text = #"23"; //DONT WORK
}
I think you forgot to reference UITextField in the storyboard with your property
#property (weak, nonatomic) IBOutlet UITextField *totalWinTextField;
that is easy you just need to select your UITextField in the storyboard holding down the key control and you drag it to your property. You can see when the property is referenced when in the left side has a circle filled.
I hope to be helpful.
From your comment, this is your viewDidLoad -
- (void)viewDidLoad {
//win
self.TotalWinTextField = 0;
//loss
self.TotalLossTextField = 0;
//stats
self.textField1 = 0;
self.textField2 = 0;
self.textField3 = 0;
[self readFilewin];
[self readFilelose];
[self readFilestats];
}
This is setting all of your IBOutlets to nil (0).
I presume that what you meant was -
- (void)viewDidLoad {
//win
self.TotalWinTextField.text = #"0";
//loss
self.TotalLossTextField.text = #"0";
//stats
self.textField1.text = #"0";
self.textField2.text = #"0";
self.textField3.text = #"0";
[self readFilewin];
[self readFilelose];
[self readFilestats];
}
First of all make sure that outlet is created correctly
Secondly, check it is properly synthesized
thridly, make sure outlet is nonatomic
change ur viewDidLoad to this
- (void)viewDidLoad {
// Do any additional setup after loading the view.
[super viewDidLoad];
//win self.TotalWinTextField = 0;
//loss self.TotalLossTextField = 0;
//stats self.textField1 = 0;
self.textField2 = 0;
self.textField3 = 0;
[self readFilewin];
[self readFilelose];
[self readFilestats];
}
Related
edit: I finally solved this, it was a combination of a caching problem and a missing line of code. I never actually added the task to the view controller, somehow I missed that step. But also I had strange errors just running the github demo project and had to reboot and sudo delete the cache directory in order to get Xcode to function as it should.
I am trying to implement Research Kit in Objective-C. There are no tutorials and very little documentation to turn to. I am getting a crash "Visual consent step has no visible scenes". I have one view controller and on that view controller I have a button that triggers the IBAction "consentTapped". I have attempted to adapt the Ray Wenderlich tutorial http://www.raywenderlich.com/104575/researchkit-tutorial-with-swift and this GitHub project: https://github.com/weberbry/ResearchKitConsentDemo
In an attempt to troubleshoot this myself I have put all the code in viewDidAppear, taking it out of encapsulated methods because I thought I made a mistake that way but there is still a problem:
Here is my code:
#import "ViewController.h"
#import <ResearchKit/ResearchKit.h>
#interface ViewController ()<ORKTaskViewControllerDelegate>
#property (strong, nonatomic) ORKConsentDocument *consentDocument;
#property (strong, nonatomic) ORKOrderedTask *orderedTask;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSString *resource = [[NSBundle mainBundle] pathForResource:#"ConsentText" ofType:#"json"];
NSData *consentData = [NSData dataWithContentsOfFile:resource];
NSDictionary *parsedConsentData = [NSJSONSerialization JSONObjectWithData:consentData options:NSJSONReadingMutableContainers error:nil];
NSArray *sectionDataParsedFromInputFile = [parsedConsentData objectForKey:#"sections"];
NSMutableArray *consentSections = [NSMutableArray new];
for (NSDictionary *sectionDictionary in sectionDataParsedFromInputFile) {
ORKConsentSectionType sectionType = [[sectionDictionary objectForKey:#"sectionType"] integerValue];
NSString *title = [sectionDictionary objectForKey:#"sectionTitle"];
NSString *summary = [sectionDictionary objectForKey:#"sectionSummary"];
NSString *detail = [sectionDictionary objectForKey:#"sectionDetail"];
ORKConsentSection *section = [[ORKConsentSection alloc] initWithType:sectionType];
section.title = title;
section.summary = summary;
section.htmlContent = detail;
ORKConsentSection *consentSection = section;
[consentSections addObject:consentSection];
}
ORKConsentSection *introSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
introSection.title = #"Intro Language";
introSection.content = #"This will only be shown in the consent document because this sectionType is map to ORKConsentSectionTypeOnlyInDocument. A consent document can include many sections with type ORKConsentSectionTypeOnlyInDocument. In this document there is a ORKConsentSectionTypeOnlyInDocument section as an intro and one as a closing section";
[consentSections insertObject:introSection atIndex:0];
ORKConsentSection *closingSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
closingSection.title = #"Additional Terms";
closingSection.htmlContent = #"Adding a ORKConsentSectionTypeOnlyInDocument at the end of a consent can be helpful to include any additional legal or related information.";
[consentSections addObject:closingSection];
self.consentDocument = [ORKConsentDocument new];
self.consentDocument.title = #"Demo Consent";
self.consentDocument.sections = consentSections;
ORKConsentSignature *signature = [ORKConsentSignature new];
self.consentDocument.signatures = [NSArray arrayWithObject:signature];
ORKVisualConsentStep *visualConsentStep = [[ORKVisualConsentStep alloc] initWithIdentifier:#"visualConsentStep" document:self.consentDocument];
ORKConsentReviewStep *consentReviewStep = [[ORKConsentReviewStep alloc] initWithIdentifier:#"consentReviewStep" signature:self.consentDocument.signatures.firstObject inDocument:self.consentDocument];
consentReviewStep.text = #"Review Consent!";
consentReviewStep.reasonForConsent = #"I confirm that I consent to join this study";
self.orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:#"consent" steps:#[visualConsentStep, consentReviewStep]];
}
- (IBAction)consentTapped:(id)sender {
ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc]initWithTask:self.orderedTask taskRunUUID:nil];
taskViewController.delegate = self;
[self presentViewController:taskViewController animated:YES completion:nil];
}
- (void)taskViewController:(ORKTaskViewController *)taskViewController
didFinishWithReason:(ORKTaskViewControllerFinishReason)reason
error:(NSError *)error {
ORKTaskResult *taskResult = [taskViewController result];
[self dismissViewControllerAnimated:YES completion:nil];
}
Due to the wording of the error I feel like there should be another view controller scene but I didn't see one on the Ray Wenderlich tutorial unless I missed it. I don't know swift at all yet so if you do and you see that I missed something please let me know.
The crash happens as you leave viewDidAppear.
Also this is my very first post here so if I have not followed community guidelines please let me know and I will modify my post at once.
edit: here is the working code. And remember, sudo delete your DerivedData folder, and reboot if you have strange errors in addition to the original error I posted. The missing line was "taskViewController.task = self.orderedTask;"
#import "ViewController.h"
#import <ResearchKit/ResearchKit.h>
#interface ViewController ()<ORKTaskViewControllerDelegate>
#property (strong, nonatomic) ORKConsentDocument *consentDocument;
#property (strong, nonatomic) ORKOrderedTask *orderedTask;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSString *resource = [[NSBundle mainBundle] pathForResource:#"ConsentText" ofType:#"json"];
NSData *consentData = [NSData dataWithContentsOfFile:resource];
NSDictionary *parsedConsentData = [NSJSONSerialization JSONObjectWithData:consentData options:NSJSONReadingMutableContainers error:nil];
NSArray *sectionDataParsedFromInputFile = [parsedConsentData objectForKey:#"sections"];
NSMutableArray *consentSections = [NSMutableArray new];
for (NSDictionary *sectionDictionary in sectionDataParsedFromInputFile) {
ORKConsentSectionType sectionType = [[sectionDictionary objectForKey:#"sectionType"] integerValue];
NSString *title = [sectionDictionary objectForKey:#"sectionTitle"];
NSString *summary = [sectionDictionary objectForKey:#"sectionSummary"];
NSString *detail = [sectionDictionary objectForKey:#"sectionDetail"];
ORKConsentSection *section = [[ORKConsentSection alloc] initWithType:sectionType];
section.title = title;
section.summary = summary;
section.htmlContent = detail;
ORKConsentSection *consentSection = section;
[consentSections addObject:consentSection];
}
ORKConsentSection *introSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
introSection.title = #"Intro Language";
introSection.htmlContent = #"This will only be shown in the consent document because this sectionType is map to ORKConsentSectionTypeOnlyInDocument. A consent document can include many sections with type ORKConsentSectionTypeOnlyInDocument. In this document there is a ORKConsentSectionTypeOnlyInDocument section as an intro and one as a closing section";
[consentSections insertObject:introSection atIndex:0];
ORKConsentSection *closingSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
closingSection.title = #"Additional Terms";
closingSection.htmlContent = #"Adding a ORKConsentSectionTypeOnlyInDocument at the end of a consent can be helpful to include any additional legal or related information.";
[consentSections addObject:closingSection];
NSArray *sections = consentSections;
self.consentDocument = [ORKConsentDocument new];
self.consentDocument.title = #"Demo Consent";
self.consentDocument.sections = consentSections;
ORKConsentSignature *signature = [ORKConsentSignature new];
self.consentDocument.signatures = [NSArray arrayWithObject:signature];
ORKVisualConsentStep *visualConsentStep = [[ORKVisualConsentStep alloc] initWithIdentifier:#"visualConsentStep" document:self.consentDocument];
ORKConsentReviewStep *consentReviewStep = [[ORKConsentReviewStep alloc] initWithIdentifier:#"consentReviewStep" signature:self.consentDocument.signatures.firstObject inDocument:self.consentDocument];
consentReviewStep.text = #"Review Consent!";
consentReviewStep.reasonForConsent = #"I confirm that I consent to join this study";
self.orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:#"consent" steps:#[visualConsentStep, consentReviewStep]];
}
- (IBAction)consentTapped:(id)sender {
ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] init];
taskViewController.task = self.orderedTask;
taskViewController.delegate = self;
[self presentViewController:taskViewController animated:YES completion:nil];
}
- (void)taskViewController:(ORKTaskViewController *)taskViewController
didFinishWithReason:(ORKTaskViewControllerFinishReason)reason
error:(NSError *)error {
ORKTaskResult *taskResult = [taskViewController result];
[self dismissViewControllerAnimated:YES completion:nil];
}
Answer by Abbey Jackson:
Here is the working code. And remember, sudo delete your DerivedData folder, and reboot if you have strange errors in addition to the original error I posted. The missing line was taskViewController.task = self.orderedTask;
#import "ViewController.h"
#import <ResearchKit/ResearchKit.h>
#interface ViewController ()<ORKTaskViewControllerDelegate>
#property (strong, nonatomic) ORKConsentDocument *consentDocument;
#property (strong, nonatomic) ORKOrderedTask *orderedTask;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSString *resource = [[NSBundle mainBundle] pathForResource:#"ConsentText" ofType:#"json"];
NSData *consentData = [NSData dataWithContentsOfFile:resource];
NSDictionary *parsedConsentData = [NSJSONSerialization JSONObjectWithData:consentData options:NSJSONReadingMutableContainers error:nil];
NSArray *sectionDataParsedFromInputFile = [parsedConsentData objectForKey:#"sections"];
NSMutableArray *consentSections = [NSMutableArray new];
for (NSDictionary *sectionDictionary in sectionDataParsedFromInputFile) {
ORKConsentSectionType sectionType = [[sectionDictionary objectForKey:#"sectionType"] integerValue];
NSString *title = [sectionDictionary objectForKey:#"sectionTitle"];
NSString *summary = [sectionDictionary objectForKey:#"sectionSummary"];
NSString *detail = [sectionDictionary objectForKey:#"sectionDetail"];
ORKConsentSection *section = [[ORKConsentSection alloc] initWithType:sectionType];
section.title = title;
section.summary = summary;
section.htmlContent = detail;
ORKConsentSection *consentSection = section;
[consentSections addObject:consentSection];
}
ORKConsentSection *introSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
introSection.title = #"Intro Language";
introSection.htmlContent = #"This will only be shown in the consent document because this sectionType is map to ORKConsentSectionTypeOnlyInDocument. A consent document can include many sections with type ORKConsentSectionTypeOnlyInDocument. In this document there is a ORKConsentSectionTypeOnlyInDocument section as an intro and one as a closing section";
[consentSections insertObject:introSection atIndex:0];
ORKConsentSection *closingSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument];
closingSection.title = #"Additional Terms";
closingSection.htmlContent = #"Adding a ORKConsentSectionTypeOnlyInDocument at the end of a consent can be helpful to include any additional legal or related information.";
[consentSections addObject:closingSection];
NSArray *sections = consentSections;
self.consentDocument = [ORKConsentDocument new];
self.consentDocument.title = #"Demo Consent";
self.consentDocument.sections = consentSections;
ORKConsentSignature *signature = [ORKConsentSignature new];
self.consentDocument.signatures = [NSArray arrayWithObject:signature];
ORKVisualConsentStep *visualConsentStep = [[ORKVisualConsentStep alloc] initWithIdentifier:#"visualConsentStep" document:self.consentDocument];
ORKConsentReviewStep *consentReviewStep = [[ORKConsentReviewStep alloc] initWithIdentifier:#"consentReviewStep" signature:self.consentDocument.signatures.firstObject inDocument:self.consentDocument];
consentReviewStep.text = #"Review Consent!";
consentReviewStep.reasonForConsent = #"I confirm that I consent to join this study";
self.orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:#"consent" steps:#[visualConsentStep, consentReviewStep]];
}
- (IBAction)consentTapped:(id)sender {
ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] init];
taskViewController.task = self.orderedTask;
taskViewController.delegate = self;
[self presentViewController:taskViewController animated:YES completion:nil];
}
- (void)taskViewController:(ORKTaskViewController *)taskViewController
didFinishWithReason:(ORKTaskViewControllerFinishReason)reason
error:(NSError *)error {
ORKTaskResult *taskResult = [taskViewController result];
[self dismissViewControllerAnimated:YES completion:nil];
}
I have 2 VC, one where the users write the data, with textfield or pickerview, and the main screen where i show the data on a tableview. The problem is that when i click on done button, it might call the delegate, but on the first vc, where is implemented, it doesnt receive any call. What should i do? I have been for 2 days trying to find the bug, and nothings happens. Thanks for any Help.
2VC.h
#protocol AddCountryDelegate <NSObject>
#required
-(void)didCreateCountry:(CountryClass*)country;
#end
#interface AddCountryViewController : UIViewController
#property (assign, nonatomic) id<AddCountryDelegate> customDelegate;
2VC.m
- (IBAction)actionDone:(id)sender {
NSString* itemName = self.itemNameTextField.text;
NSString* countryName = self.countryNameTextField.text;
NSDate *countryDate = [datePickerView date];
NSString *daysLeftString = [NSString stringWithFormat:#"%# days", self.daysLeftTextField.text];
NSInteger daysLeftInt = [daysLeftString integerValue];
NSNumber *daysLeft = [NSNumber numberWithInteger:daysLeftInt];
NSString *paymentMethod = self.paymentMethodTextField.text;
CountryClass* newCountryItem =
[[CountryClass alloc] initWithCountryName:countryName countryLogo:#"" itemName:itemName countryDate:countryDate daysLeft:daysLeft andPaymentMethod:paymentMethod];
[self.customDelegate didCreateCountry:newCountryItem];
[self dismissViewControllerAnimated:YES completion:nil];
}
And finally the implementation on the 1st VC:
-(void)didCreateCountry:(CountryClass *)country{
//Add new country-itemCountry - UPDATING OUR MODEL DATA
NSMutableArray *mutableCountries = [self.countries mutableCopy];
[mutableCountries addObject:country];
self.countries = [mutableCountries copy];
//UPDATING THE VIEW
[self.tableView reloadData];
NSLog(#"Created");
[self saveCountriesToDisc];
}
-(void)saveCountriesToDisc{
NSMutableArray* convertedCountries = [NSMutableArray array];
//Converting the model to dictionary
for(CountryClass *country in self.countries)
{
NSDictionary *convertedCountry = [shop countriesToDictionary];
[convertedCountries addObject:convertedCountry];
}
//NOW convertedShows CONTAINS ONLY STRINGS, NUMBERS,
//ARRAYS AND DICTIONARY
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths.firstObject;
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:#"countriesListData.plist"];
//NOW TELL THE ARRAY TO SAVE
[convertedCountries writeToFile:destinationPath atomically:YES];
NSLog(#"Saved");
[self.tableView reloadData];
}
I initialize my delegate on the prepareforsegue
-(void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
if ([segue.identifier isEqualToString:#"AddSegue"]) {
AddCountryViewController* addCountryVC =
segue.destinationViewController;
addCountryVC.customDelegate = self;
}
where in VC1 did you set the customDelegate to self?
also you should set your delegate to weak not assign
I am trying to implement the google map module to set the control parameters before adding the mARKER
The wayout is to initiate acquire the result of new viewController via NSBUndles. My desire goal is to redirect to the sameViewController as expected result.
But when it comes to the implementation , it loads the actual result:
Expected result:
Actual result
Would you please tell me what other details for instantiate a new ViewController with all UI elements being set as expected viewControllers? I swear that the new ViewController has all require elements being set on?
The actual console message writes:
2014-06-18 17:50:37.766 marker[1469:60b] Text=2014-06-18 17:50:36
2014-06-18 17:50:41.102 marker[1469:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x17daf180>) doesn't contain a view controller with identifier 'SliderViewController''
*** First throw call stack:
(0x3102dfd3 0x3b7dcccf 0x33d1bfb7 0x7e155 0x31031584 0x30f7c0db 0x30f7f873 0x231ffb 0x310300f1 0x30f7f7b8 0x20d6bb 0x138133 0x155319 0x339d000d 0x3387b503 0x33c22af5 0x33842373 0x33840abb 0x30ff92a5 0x30ff6c49 0x30ff6f8b 0x30f61f0f 0x30f61cf3 0x35e66663 0x338ad16d 0x7f4ed 0x3bce9ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
The below is my code
-(void) mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate{
sliderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SliderViewController"];
sliderVC.view.backgroundColor = [UIColor yellowColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:sliderVC animated:YES completion:NULL];
}
Code for new viewCOntroller (.m) only:
#import "SliderViewController.h"
#import <AudioToolbox/AudioServices.h>
#import "EFCircularSlider.h"
#interface SliderViewController (){
NSString *valueV;
NSString *valueC;
}
#end
#implementation SliderViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_uiSlider.minimumValue = 0.0;
_uiSlider.maximumValue = 100.0;
[_uiSlider removeConstraints:_uiSlider.constraints];
[_uiSlider setTranslatesAutoresizingMaskIntoConstraints:YES];
float value = M_PI * -0.5 ;
_uiSlider.transform = CGAffineTransformMakeRotation(value);
CGRect sliderFrame = CGRectMake(60, 300, 100, 100);
EFCircularSlider* circularSlider = [[EFCircularSlider alloc] initWithFrame:sliderFrame];
[circularSlider addTarget:self action:#selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:circularSlider];
[circularSlider setCurrentValue:10.0f];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)valueChanged:(EFCircularSlider*)slider {
self.uiValue2.text = [NSString stringWithFormat:#"%.02f", slider.currentValue ];
valueC = self.uiValue2.text;
if(slider.currentValue > 20.0 && slider.currentValue < 30.0 ){
AudioServicesPlaySystemSound(1003);
// AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
- (IBAction)reset:(id)sender {
[self writeToTextFile:valueV :valueC];
self.uiValue.text =[NSString stringWithFormat:#"%.2f" , 0.00];
[self.uiSlider setValue:0.00];
}
-(void) writeToTextFile:(NSString*) values : (NSString*) values2 {
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/slider.txt",documentsDirectory];
//create content - four lines of text
NSString *content = [NSString stringWithFormat:#"%#%#%#%#", values , #"\n" , values2 , #"\n" ];
//save content to the documents directory
[content writeToFile:fileName
atomically:YES
encoding:NSStringEncodingConversionAllowLossy
error:nil];
NSLog(#"%#",documentsDirectory);
[self displayContent];
}
-(void) displayContent{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/slider.txt",
documentsDirectory];
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
//use simple alert from my library (see previous post for details)
NSLog(#"%#",content);
// [self showEmail:fileName];
}
- (IBAction)sliderChange:(id)sender {
UISlider *slider = (UISlider *)sender;
NSString *newValue = [NSString stringWithFormat:#"%.2f" , slider.value];
self.uiValue.text = newValue;
valueV = self.uiValue.text;
if(slider.value > 30 && slider.value < 50){
AudioServicesPlaySystemSound(1003);
//AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
When creating the new view controller, you have to instantiate it with a nib file, something like:
sliderVC = [[SliderViewController alloc] initWithNibName:#"SliderViewController" bundle:nil]
or if you use storyboards:
sliderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SliderViewController"];
Otherwise there is no connection to the file that you created in Interface Builder and iOS doesn't know what UI elements to load for this view controller.
Update: this is where you have to set the string:
Adding to #Nikolas Burk answer - if you have all your Viewcontrollers on one storyboard, you can instantiate them like this :
MyClassViewController *next = [self.storyboard instantiateViewControllerWithIdentifier:#"name"];
The name is set in InterfaceBuilder.
So i want to print the users in an NSMutableArray. But the strings keep coming out as nil.
here is what i have:
int users = 0;
- (IBAction)addNewUser:(id)sender {
NSString *string;
string = userNameTextField.text;
[usernameArray insertObject:string atIndex:users];
users++;
[self showUsers];
}
-(void)showUsers{
for (int i = 0; i < users; i++){
NSString *s = textView.text;
NSString *add;
add = [NSString stringWithFormat:#"%# ",[usernameArray objectAtIndex:i]];
NSString *display = [NSString stringWithFormat:#"%# \n %#", s, add];
textView.text = display;
}
}
i have also tried
-(void)showUsers{
for (int i = 1; i < users; i++){
NSString *s = textView.text;
NSString *add;
add = [usernameArray objectAtIndex:i];
NSString *display = [NSString stringWithFormat:#"%# \n %#", s, add];
textView.text = display;
}
}
First of all try using more comprehensive names for the objects. I'm rewriting your code.
Common Causes for the problem : Array not initialized, you are starting your for cycle with int i equal to 1, so you are missing the object at index 0 at your mutable array. Try the following code.
#interface InterfaceName : InterfaceInherits <IfDelegate> {
int usersCount;
NSMutableArray * usernameArray;
}
#implementation InterfaceName
/*There's no more confident way to initialize a variable than in the init method of the class. */
-(id)init{
usersCount = 0;
//You have to be sure that your array is not nil
usernameArray = [NSMutableArray alloc]init]];
return self;
}
- (IBAction)addNewUser:(id)sender {
NSString *username = [usernameTextField text];
[usernameArray insertObject:username atIndex:usersCount];
usersCount++;
//I'll omit the display as I'm not sure what you were doing with it.
}
-(void)showUsers{
for (int i = 0; i < usersCount; i++){
NSString *retrievedUser = [usernameArray objectAtIndex:i];
NSString *display = [NSString stringWithFormat:#"User Retrieved : %#",retrievedUser];
textView.text = display;
}
}
#end
So I currently have a functioning way of saving settings for my Cocos2d game, and the method I am using is an XML parser.
First of all, is it better to use NSUserDefaults for something like this?
EDIT: I DO APPOLOGIZE FOR THE LONG POST, IF YOU ALREADY KNOW HOW AN XML PARSER WORKS JUST SKIP TO THE END.
Here is my GlobalSettings.h:
#import <Foundation/Foundation.h>
#interface GlobalSettings : NSObject {
// Declare variables with an underscore in front, for example:
int _currency;
BOOL _BankerBossDefeated;
BOOL _BabyBossDefeated;
BOOL _DuckBossDefeated;
BOOL _BaseBallBossDefeated;
BOOL _NewtonBossDefeated;
BOOL _CatchExtender;
BOOL _CatchExtenderEnabled;
BOOL _SpeedBoost;
BOOL _SpeedBoostEnabled;
}
// Declare your variable properties without an underscore, for example:
#property (nonatomic, assign) int currency;
#property (nonatomic, assign) BOOL BankerBossDefeated;
#property (nonatomic, assign) BOOL BabyBossDefeated;
#property (nonatomic, assign) BOOL DuckBossDefeated;
#property (nonatomic, assign) BOOL BaseBallBossDefeated;
#property (nonatomic, assign) BOOL NewtonBossDefeated;
#property (nonatomic, assign) BOOL SpeedBoost;
#property (nonatomic, assign) BOOL CatchExtender;
#property (nonatomic, assign) BOOL SpeedBoostEnabled;
#property (nonatomic, assign) BOOL CatchExtenderEnabled;
// Put your custom init method interface here:
-(id)initWithcurrency:(int)currency
BankerBossDefeated:(BOOL)BankerBossDefeated
BabyBossDefeated:(BOOL)BabyBossDefeated
DuckBossDefeated:(BOOL)DuckBossDefeated
BaseBallBossDefeated:(BOOL)BaseBallBossDefeated
NewtonBossDefeated:(BOOL)NewtonBossDefeated
CatchExtender:(BOOL)CatchExtender
SpeedBoost:(BOOL)SpeedBoost
CatchExtenderEnabled:(BOOL)CatchExtenderEnabled
SpeedBoostEnabled:(BOOL)SpeedBoostEnabled;
#end
My GlobalSettings.m is:
#import "GlobalSettings.h"
#implementation GlobalSettings
// Synthesize your variables here, for example:
#synthesize currency = _currency;
#synthesize BankerBossDefeated = _BankerBossDefeated;
#synthesize BabyBossDefeated = _BabyBossDefeated;
#synthesize DuckBossDefeated = _DuckBossDefeated;
#synthesize BaseBallBossDefeated = _BaseBallBossDefeated;
#synthesize NewtonBossDefeated = _NewtonBossDefeated;
#synthesize SpeedBoost = _SpeedBoost;
#synthesize CatchExtender = _CatchExtender;
#synthesize SpeedBoostEnabled = _SpeedBoostEnabled;
#synthesize CatchExtenderEnabled = _CatchExtenderEnabled;
// put your custom init method here which takes a variable
// for each class instance variable
-(id)initWithcurrency:(int)currency
BankerBossDefeated:(BOOL)BankerBossDefeated
BabyBossDefeated:(BOOL)BabyBossDefeated
DuckBossDefeated:(BOOL)DuckBossDefeated
BaseBallBossDefeated:(BOOL)BaseBallBossDefeated
NewtonBossDefeated:(BOOL)NewtonBossDefeated
CatchExtender:(BOOL)CatchExtender
SpeedBoost:(BOOL)SpeedBoost
CatchExtenderEnabled:(BOOL)CatchExtenderEnabled
SpeedBoostEnabled:(BOOL)SpeedBoostEnabled;{
if ((self = [super init])) {
// Set class instance variables based on values
// given to this method
self.currency = currency;
self.BankerBossDefeated = BankerBossDefeated;
self.BabyBossDefeated = BabyBossDefeated;
self.DuckBossDefeated = DuckBossDefeated;
self.BaseBallBossDefeated = BaseBallBossDefeated;
self.NewtonBossDefeated = NewtonBossDefeated;
self.CatchExtender = CatchExtender;
self.SpeedBoost = SpeedBoost;
self.CatchExtenderEnabled = CatchExtenderEnabled;
self.SpeedBoostEnabled = SpeedBoostEnabled;
}
return self;
}
- (void) dealloc {
[super dealloc];
}
#end
I then parse the XML with SettingsParser.h:
#import <Foundation/Foundation.h>
#class GlobalSettings;
#interface SettingsParser : NSObject {}
+ (GlobalSettings *)loadData;
+ (void)saveData:(GlobalSettings *)saveData;
#end
and SettingsParser.m:
#import "SettingsParser.h"
#import "GlobalSettings.h"
#import "GDataXMLNode.h"
#implementation SettingsParser
+ (NSString *)dataFilePath:(BOOL)forSave {
NSString *xmlFileName = #"GlobalSettings";
/***************************************************************************
This method is used to set up the specified xml for reading/writing.
Specify the name of the XML file you want to work with above.
You don't have to worry about the rest of the code in this method.
***************************************************************************/
NSString *xmlFileNameWithExtension = [NSString stringWithFormat:#"%#.xml",xmlFileName];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentsPath = [documentsDirectory stringByAppendingPathComponent:xmlFileNameWithExtension];
if (forSave || [[NSFileManager defaultManager] fileExistsAtPath:documentsPath]) {
return documentsPath;
NSLog(#"%# opened for read/write",documentsPath);
} else {
NSLog(#"Created/copied in default %#",xmlFileNameWithExtension);
return [[NSBundle mainBundle] pathForResource:xmlFileName ofType:#"xml"];
}
}
+ (GlobalSettings *)loadData {
/***************************************************************************
This loadData method is used to load data from the xml file
specified in the dataFilePath method above.
MODIFY the list of variables below which will be used to create
and return an instance of TemplateData at the end of this method.
***************************************************************************/
int currency;
BOOL BankerBossDefeated;
BOOL BabyBossDefeated;
BOOL DuckBossDefeated;
BOOL BaseBallBossDefeated;
BOOL NewtonBossDefeated;
BOOL CatchExtender;
BOOL SpeedBoost;
BOOL CatchExtenderEnabled;
BOOL SpeedBoostEnabled;
// Create NSData instance from xml in filePath
NSString *filePath = [self dataFilePath:FALSE];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; NSLog(#"xml file is empty!");}
NSLog(#"Loading %#", filePath);
/***************************************************************************
This next line will usually have the most customisation applied because
it will be a direct reflection of what you want out of the XML file.
***************************************************************************/
NSArray *dataArray = [doc nodesForXPath:#"//GlobalSettings" error:nil];
NSLog(#"Array Contents = %#", dataArray);
/***************************************************************************
We use dataArray to populate variables created at the start of this
method. For each variable you will need to:
1. Create an array based on the elements in the xml
2. Assign the variable a value based on data in elements in the xml
***************************************************************************/
for (GDataXMLElement *element in dataArray) {
NSArray *currencyArray = [element elementsForName:#"currency"];
NSArray *BankerBossDefeatedArray = [element elementsForName:#"BankerBossDefeated"];
NSArray *BabyBossDefeatedArray = [element elementsForName:#"BabyBossDefeated"];
NSArray *DuckBossDefeatedArray = [element elementsForName:#"DuckBossDefeated"];
NSArray *BaseBallBossDefeatedArray = [element elementsForName:#"BaseBallBossDefeated"];
NSArray *NewtonBossDefeatedArray = [element elementsForName:#"NewtonBossDefeated"];
NSArray *CatchExtenderArray = [element elementsForName:#"CatchExtender"];
NSArray *SpeedBoostArray = [element elementsForName:#"SpeedBoost"];
NSArray *CatchExtenderEnabledArray = [element elementsForName:#"CatchExtenderEnabled"];
NSArray *SpeedBoostEnabledArray = [element elementsForName:#"SpeedBoostEnabled"];
// currency
if (currencyArray.count > 0) {
GDataXMLElement *currencyElement = (GDataXMLElement *) [currencyArray objectAtIndex:0];
currency = [[currencyElement stringValue] intValue];
}
// BankerBossDefeated
if (BankerBossDefeatedArray.count > 0) {
GDataXMLElement *BankerBossDefeatedElement = (GDataXMLElement *) [BankerBossDefeatedArray objectAtIndex:0];
BankerBossDefeated = [[BankerBossDefeatedElement stringValue] boolValue];
}
// DuckBossDefeated
if (DuckBossDefeatedArray.count > 0) {
GDataXMLElement *DuckBossDefeatedElement = (GDataXMLElement *) [DuckBossDefeatedArray objectAtIndex:0];
DuckBossDefeated = [[DuckBossDefeatedElement stringValue] boolValue];
}
// BabyBossDefeated
if (BabyBossDefeatedArray.count > 0) {
GDataXMLElement *BabyBossDefeatedElement = (GDataXMLElement *) [BabyBossDefeatedArray objectAtIndex:0];
BabyBossDefeated = [[BabyBossDefeatedElement stringValue] boolValue];
}
// BaseBallBossDefeated
if (BaseBallBossDefeatedArray.count > 0) {
GDataXMLElement *BaseBallBossDefeatedElement = (GDataXMLElement *) [BaseBallBossDefeatedArray objectAtIndex:0];
BaseBallBossDefeated = [[BaseBallBossDefeatedElement stringValue] boolValue];
}
// NewtonBossDefeated
if (NewtonBossDefeatedArray.count > 0) {
GDataXMLElement *NewtonBossDefeatedElement = (GDataXMLElement *) [NewtonBossDefeatedArray objectAtIndex:0];
NewtonBossDefeated = [[NewtonBossDefeatedElement stringValue] boolValue];
}
// CatchExtender
if (CatchExtenderArray.count > 0) {
GDataXMLElement *CatchExtenderElement = (GDataXMLElement *) [CatchExtenderArray objectAtIndex:0];
CatchExtender = [[CatchExtenderElement stringValue] boolValue];
}
// SpeedBoost
if (SpeedBoostArray.count > 0) {
GDataXMLElement *SpeedBoostElement = (GDataXMLElement *) [SpeedBoostArray objectAtIndex:0];
SpeedBoost = [[SpeedBoostElement stringValue] boolValue];
}
// CatchExtenderEnabled
if (CatchExtenderEnabledArray.count > 0) {
GDataXMLElement *CatchExtenderEnabledElement = (GDataXMLElement *) [CatchExtenderEnabledArray objectAtIndex:0];
CatchExtenderEnabled = [[CatchExtenderEnabledElement stringValue] boolValue];
}
// SpeedBoost
if (SpeedBoostEnabledArray.count > 0) {
GDataXMLElement *SpeedBoostEnabledElement = (GDataXMLElement *) [SpeedBoostEnabledArray objectAtIndex:0];
SpeedBoostEnabled = [[SpeedBoostEnabledElement stringValue] boolValue];
}
}
/***************************************************************************
Now the variables are populated from xml data we create an instance of
TemplateData to pass back to whatever called this method.
The initWithExampleInt:exampleBool:exampleString will need to be replaced
with whatever method you have updaed in the TemplateData class.
***************************************************************************/
//NSLog(#"XML value read for exampleInt = %i", exampleInt);
//NSLog(#"XML value read for exampleBool = %i", exampleBool);
//NSLog(#"XML value read for exampleString = %#", exampleString);
GlobalSettings *Data = [[GlobalSettings alloc] initWithcurrency:currency
BankerBossDefeated:BankerBossDefeated
BabyBossDefeated:BabyBossDefeated DuckBossDefeated:DuckBossDefeated BaseBallBossDefeated:BaseBallBossDefeated NewtonBossDefeated:NewtonBossDefeated
CatchExtender:CatchExtender
SpeedBoost:SpeedBoost CatchExtenderEnabled:CatchExtenderEnabled
SpeedBoostEnabled:SpeedBoostEnabled];
[doc release];
[xmlData release];
return Data;
[Data release];
}
+ (void)saveData:(GlobalSettings *)saveData {
/***************************************************************************
This method writes data to the xml based on a TemplateData instance
You will have to be very aware of the intended xml contents and structure
as you will be wiping and re-writing the whole xml file.
We write an xml by creating elements and adding 'children' to them.
You'll need to write a line for each element to build the hierarchy // <-- MODIFY CODE ACCORDINGLY
***************************************************************************/
GDataXMLElement *GlobalSettingsElement = [GDataXMLNode elementWithName:#"GlobalSettings"];
GDataXMLElement *currencyElement = [GDataXMLNode elementWithName:#"currency"
stringValue:[[NSNumber numberWithInt:saveData.currency] stringValue]];
GDataXMLElement *BankerBossDefeatedElement = [GDataXMLNode elementWithName:#"BankerBossDefeated"
stringValue:[[NSNumber numberWithBool:saveData.BankerBossDefeated] stringValue]];
GDataXMLElement *BabyBossDefeatedElement = [GDataXMLNode elementWithName:#"BabyBossDefeated"
stringValue:[[NSNumber numberWithBool:saveData.BabyBossDefeated] stringValue]];
GDataXMLElement *DuckBossDefeatedElement = [GDataXMLNode elementWithName:#"DuckBossDefeated"
stringValue:[[NSNumber numberWithBool:saveData.DuckBossDefeated] stringValue]];
GDataXMLElement *BaseBallBossDefeatedElement = [GDataXMLNode elementWithName:#"BaseBallBossDefeated"
stringValue:[[NSNumber numberWithBool:saveData.BaseBallBossDefeated] stringValue]];
GDataXMLElement *NewtonBossDefeatedElement = [GDataXMLNode elementWithName:#"NewtonBossDefeated"
stringValue:[[NSNumber numberWithBool:saveData.NewtonBossDefeated] stringValue]];
GDataXMLElement *CatchExtenderElement = [GDataXMLNode elementWithName:#"CatchExtender"
stringValue:[[NSNumber numberWithBool:saveData.CatchExtender] stringValue]];
GDataXMLElement *SpeedBoostElement = [GDataXMLNode elementWithName:#"SpeedBoost"
stringValue:[[NSNumber numberWithBool:saveData.SpeedBoost] stringValue]];
GDataXMLElement *CatchExtenderEnabledElement = [GDataXMLNode elementWithName:#"CatchExtenderEnabled"
stringValue:[[NSNumber numberWithBool:saveData.CatchExtender] stringValue]];
GDataXMLElement *SpeedBoostEnabledElement = [GDataXMLNode elementWithName:#"SpeedBoostEnabled"
stringValue:[[NSNumber numberWithBool:saveData.SpeedBoost] stringValue]];
// Using the elements just created, set up the hierarchy
[GlobalSettingsElement addChild:currencyElement];
[GlobalSettingsElement addChild:BankerBossDefeatedElement];
[GlobalSettingsElement addChild:BabyBossDefeatedElement];
[GlobalSettingsElement addChild:DuckBossDefeatedElement];
[GlobalSettingsElement addChild:BaseBallBossDefeatedElement];
[GlobalSettingsElement addChild:NewtonBossDefeatedElement];
[GlobalSettingsElement addChild:CatchExtenderElement];
[GlobalSettingsElement addChild:SpeedBoostElement];
[GlobalSettingsElement addChild:CatchExtenderEnabledElement];
[GlobalSettingsElement addChild:SpeedBoostEnabledElement];
GDataXMLDocument *document = [[[GDataXMLDocument alloc]
initWithRootElement:GlobalSettingsElement] autorelease];
NSData *xmlData = document.XMLData;
NSString *filePath = [self dataFilePath:TRUE];
NSLog(#"Saving data to %#...", filePath);
[xmlData writeToFile:filePath atomically:YES];
}
#end
EDIT: THE ACTUAL PROBLEM BEGINS HERE:
In my menu class I have two switches that come up when CatchExtender and SpeedBoost become enabled (they are purchased in the game's store). In those switches, I want to set SpeedBoostEnabled and CatchExtenderEnabled depending on the switch.
These are the switches:
IN MY INIT:
if (GlobalSettings.CatchExtender == TRUE) {
if(GlobalSettings.SpeedBoost == TRUE){
catchSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(220, 400, 10, 10)];
catchSwitch.center = CGPointMake(240, 450);
CCLabelTTF *catchLabel = [CCLabelTTF labelWithString:#"Catch Extender" fontName:#"Chalkduster" fontSize:15];
catchLabel.color = ccWHITE;
catchLabel.position = CGPointMake(240, 60);
[self addChild: catchLabel];
}else{
catchSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(160, 400, 10, 10)];
catchSwitch.center = CGPointMake(160, 450);
CCLabelTTF *catchLabel = [CCLabelTTF labelWithString:#"Catch Extender" fontName:#"Chalkduster" fontSize:15];
catchLabel.color = ccWHITE;
catchLabel.position = CGPointMake(160, 60);
[self addChild: catchLabel];
}
catchSwitch.on = NO; //set to be OFF at start
catchSwitch.tag = 1; // this is not necessary - only to find later
[catchSwitch addTarget:self action:#selector(catchAction:) forControlEvents:UIControlEventValueChanged];
[[[CCDirector sharedDirector] openGLView] addSubview:catchSwitch];
}
if (GlobalSettings.SpeedBoost == TRUE) {
if(GlobalSettings.CatchExtender == TRUE){
speedSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(100, 400, 10, 10)];
speedSwitch.center = CGPointMake(80, 450);
CCLabelTTF *speedLabel = [CCLabelTTF labelWithString:#"Speed Enhancer" fontName:#"Chalkduster" fontSize:15];
speedLabel.color = ccWHITE;
speedLabel.position = CGPointMake(80, 60);
[self addChild: speedLabel];
}else{
speedSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(160, 400, 10, 10)];
speedSwitch.center = CGPointMake(160, 450);
}
speedSwitch.on = NO; //set to be OFF at start
speedSwitch.tag = 1; // this is not necessary - only to find later
[speedSwitch addTarget:self action:#selector(speedAction:) forControlEvents:UIControlEventValueChanged];
[[[CCDirector sharedDirector] openGLView] addSubview:speedSwitch];
}
IN THE ACTIONS:
- (void)catchAction:(id)sender
{
// Your logic when the switch it used
// NSLog(#"switchAction: value = %d", [sender isOn]);
if ([sender isOn]) {
GlobalSettings *GlobalSettings = [SettingsParser loadData];
GlobalSettings.CatchExtenderEnabled = TRUE;
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"ON"];
[dialog setMessage:#"Catch Extender is on"];
[dialog addButtonWithTitle:#"Sweet!"];
[dialog show];
[dialog release];
[SettingsParser saveData:GlobalSettings];
}else{
GlobalSettings *GlobalSettings = [SettingsParser loadData];
GlobalSettings.CatchExtenderEnabled = FALSE;
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"OFF"];
[dialog setMessage:#"Catch Extender is off"];
[dialog addButtonWithTitle:#"Thanks"];
[dialog show];
[dialog release];
[SettingsParser saveData:GlobalSettings];
}
}
- (void)speedAction:(id)sender
{
// Your logic when the switch it used
// NSLog(#"switchAction: value = %d", [sender isOn]);
if ([sender isOn]) {
GlobalSettings *GlobalSettings = [SettingsParser loadData];
GlobalSettings.SpeedBoostEnabled = TRUE;
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"ON"];
[dialog setMessage:#"Speed Enhancer is on"];
[dialog addButtonWithTitle:#"Sweet!"];
[dialog show];
[dialog release];
[SettingsParser saveData:GlobalSettings];
}else{
GlobalSettings *GlobalSettings = [SettingsParser loadData];
GlobalSettings.SpeedBoostEnabled = FALSE;
UIAlertView* dialog = [[UIAlertView alloc] init];
[dialog setDelegate:self];
[dialog setTitle:#"OFF"];
[dialog setMessage:#"Speed Enhancer is off"];
[dialog addButtonWithTitle:#"Thanks"];
[dialog show];
[dialog release];
[SettingsParser saveData:GlobalSettings];
}
}
In the classes that hold the data for the game levels, I check these Booleans normally with a simple if statement. But it doesn't seem to work, the settings don't seem to save because in the Log it doesn't seem like the values have changed in the XML file..
Again sorry for the long post but this issue is kinda bugging me.
I've never used Cocos2D before but this seems like exactly what you would use NSUserDefaults for in a typical iOS app, like this: [[NSUserDefaults standardUserDefaults] setBool:YES ForKey:#"Key"];