An AppDelegate's property is unexpectedly set to null - objective-c

First of all, I really appreciate your helps.
Well, I use three NSString objects in common in two views. And these view is segued by Embedded NavigationController, I mean I start programming with SingleView.
In AppDelegate.h, I write
#property (weak, nonatomic) NSString *crntURL;
#property (weak, nonatomic) NSString *crntTitle;
#property (weak, nonatomic) NSString *crntHTML;
for delegation.
And in the first view, I have a webview and write
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSString *url = [[NSString alloc] initWithString:[myWebView stringByEvaluatingJavaScriptFromString:#"document.URL"]];
NSString *title = [[NSString alloc] initWithString:[myWebView stringByEvaluatingJavaScriptFromString:#"document.title"]];
NSString *html = [[NSString alloc] initWithString:[myWebView stringByEvaluatingJavaScriptFromString:#"document.all[0].outerHTML"]];
appDelegate.crntTitle = nil;
appDelegate.crntTitle = [[NSString alloc] initWithString:title];
appDelegate.crntHTML = nil;
appDelegate.crntHTML = [[NSString alloc] initWithString:html];
appDelegate.crntURL = nil;
appDelegate.crntURL = [[NSString alloc] initWithString:url];
}
Here, when I put NSLog, the expected HTML source code is dumped.
And in the second view(a subclass of UIViewController), I write
- (void)viewDidLoad
{
// Do any additional setup after loading the view.
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
sourceHTML.text = appDelegate.crntHTML;
NSLog( #"%#", appDelegate.crntHTML );
NSLog( #"%#", appDelegate.crntURL );
NSLog( #"%#", appDelegate.crntTitle );
[super viewDidLoad];
}
and only crntHTML is unexpectedly set to null while crntURL and crntTitle keep values.
Do you have any ideas?
Thank you in advance.
Masaru

You've declared your properties in the app delegate as weak.
Using ARC, an object will be released and set to nil if there's no strong reference to it.
I could imagine you're referencing the title and URL variable from the first view controller, but the HTML variable is only referenced in the second view controller. Once you're ready to show the HTML in the second controller, it has already been released, since the app delegate is not holding on to it.
Try changing the property declarations in the app delegate to strong:
#property (strong, nonatomic) NSString *crntURL;
#property (strong, nonatomic) NSString *crntTitle;
#property (strong, nonatomic) NSString *crntHTML;

Related

iOS Passing (Retain) the value of an NSMutableArray to another NSMutableArray in another view

I'm using .XIB and without ARC. I'm passing the value of the NSMultableArray to another view, if I put [self presentModel...], it works, but if I call the AnotherView with a button the value of the NSMultableArray of the AnotherView is null!
AnotherView.h
#interface AnotherViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>{
NSMutableArray *otherAnother;
NSMutableArray *arrayOfTheAnotherView;
}
#property (retain, nonatomic) IBOutlet UITableView *tableView;
#property (retain, nonatomic) NSMutableArray *arrayOfTheAnotherView;
AnotherView.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
otherAnother = [[NSMutableArray alloc]init];
otherAnother = [[NSMutableArray alloc]initWithArray:self.arrayOfTheAnotherView];
//    [otherAnother addObjectsFromArray:arrayOfTheAnotherView];
NSLog(#"%#", self.arrayOfTheAnotherView);
}
The NSLog has written "null"
CurrentView.h
#interface CurrentViewController : UIViewController {
NSMutableArray * arrayCurrentView;
AnotherViewController *superAnotherView;
}
#property (retain, nonatomic) AnotherViewController *superAnotherView;
CurrentView.m
#synthesize superAnotherView;
NSString *x = [[NSString alloc]initWithFormat:#"%#",[label text]];
arrayCurrentView = [[NSMutableArray alloc]init];
[arrayCurrentView retain];
[arrayCurrentView addObject:x];
self.superAnotherView = [[AnotherViewController alloc]initWithNibName:nil bundle:nil];
self.superAnotherView.arrayOfTheAnotherView = [[NSMutableArray alloc]init];
[self.superAnotherView.arrayOfTheAnotherView retain];
[self.superAnotherView.arrayOfTheAnotherView addObjectsFromArray:arrayCurrentView];
I don't know how to retain the value of the NSMultableArray, thanks the help.
It is how I call the AnotherView:
UIButton *buttonAnother = [UIButton buttonWithType:UIButtonTypeCustom]; [buttonAnother setTag:5]; [buttonAnother addTarget:self action:#selector(switchTabBar:) forControlEvents:UIControlEventTouchDown];
[tabBarViewController.view addSubview:buttonAnother];
- (IBAction)switchTabBar:(id)sender { switch ([(UIButton *)sender tag]) { case 5: [self.tabBarController setSelectedIndex:0]; break; }
These should not be necessary:
self.superAnotherView.arrayOfTheAnotherView = [[NSMutableArray alloc]init];
[self.superAnotherView.arrayOfTheAnotherView retain];
Properties are already initialized when the class is initialized.
In fact, your explicit retain lines shouldn't be necessary at all; you're not releasing them as far as I can see and just making the retain count 2 so that it has to be released twice.
I think there's something going on here that the methods and view controllers are not being called in the order you want, probably something to do with the tab bar.
I dicoverd! I'm using the MVC
A array of the APP delegate don't lost its value.
AppDelegate
NSMutableArray *arrayDelegate;
View.m
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate.arrayDelegatePedido addObject:#"title"]; //for example

Passing data between classes is not working

I'm trying to pass NSDictionary between classes. In my AppDelegate I have instance NSDictionary.
#interface AppDelegate : UIResponder <UIApplicationDelegate, FBSessionDelegate, FBRequestDelegate>
{
NSDictionary *contactsFromFacebook;
}
#property (strong, nonatomic) NSDictionary *contactsFromFacebook;
In my AppDelegate.m file I synthesized it as #synthesize contactsFromFacebook = _contactsFromFacebook;. Next my step (filling dictionary):
-(void)request:(FBRequest *)request didLoad:(id)result {
_contactsFromFacebook = [[NSDictionary alloc]initWithDictionary:result];
}
In my someClass.m file I want to use data from contactsFromFacebook dictionary.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *someNewDictionary = [[NSDictionary alloc] initWithDictionary:appDelegate.contactsFromFacebook];
But my someNewDictionary is ampty. What I'm doing wrong?
In appDelegate write a method:
-(NSDictionary*)getSomething { return self.contactsFromFacebook; }
And then in other class:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *someNewDictionary = [[NSDictionary alloc] initWithDictionary:[appDelegate getSomething]];
And this works fine for me.
Edit:
#Abizern comment i think resolve your issue. He is right.
"#synthesize contactsFromFacebook = _contactsFromFacebook;"
Where is _contactsFromFacebook?
All I see are the following declarations:-
NSDictionary *contactsFromFacebook;
and
#property (strong, nonatomic) NSDictionary *contactsFromFacebook;
I see no link between the strong property contactsFromFacebook and the variable _contactsFromFacebook you assign to point at the NSDictionary you instantiate

Accessing global variable?

I have the following code to login to a web service and store the authentication token:
loginViewController.h
#interface loginViewController : UIViewController<XMLRPCConnectionDelegate>
#property (strong, nonatomic) IBOutlet UITextField *SSO;
#property (weak, nonatomic) IBOutlet UITextField *PASS;
#property (weak, nonatomic) IBOutlet UITextView *LoginError;
#property (nonatomic, retain) NSString *token;
#end
loginViewcontroller.m
#import "loginViewController.h"
#implementation loginViewController
#synthesize SSO;
#synthesize PASS;
#synthesize LoginError;
#synthesize token;
- (IBAction)coreLoginClicked:(id)sender {
NSURL *URL = [NSURL URLWithString: #"https://somesite"];
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL: URL];
XMLRPCConnectionManager *manager = [XMLRPCConnectionManager sharedManager];
[request setMethod:#"systemLogin" withParameters:[NSArray arrayWithObjects: SSO.text, PASS.text, nil]];
[manager spawnConnectionWithXMLRPCRequest: request delegate: self];
NSLog(#"Request body: %#", [request body]);
}
- (void)request: (XMLRPCRequest *)request didReceiveResponse: (XMLRPCResponse *)response {
if (![response faultCode]) {
token = [response object];
[self performSegueWithIdentifier:#"loginSegue" sender:self];
NSLog(#"Response object: %#", [response object]);
}
I have this code in my view controller that is displayed after successful login:
loginViewController* login = [[loginViewController alloc] init];
NSLog(#"Token: %#", login.token);
The value of login.token is nil. What am I doing wrong here? Is this the incorrect way of setting and accessing a global variable?
I was following the tutorial on Objective-C from lynda.com, and this way how they did it.. but maybe I missed something.
Thanks!
You're allocating a new instance, which means it'll be empty. If you want to be able to store objects in a class, you will have to use that instance to get the variables back.
Try accessing token via self:
NSLog(#"Token: %#", self.token);
Your second code bit does this: creates a new instance of the loginVC, and then checks to see if it has a token. You need to instantiate your loginVC, then do your login, and then it will have a value in token. Whatever class/method instantiates the loginVC will then be able to check that instance of loginVC for the token.

Gaining access to an NSMutableArray

I am new to arrays and objects. I have a class HowToPlay.h (of course that has a .m also) their i define two arrays
NSMutableArray *nibs;
NSMutableArray *unusedNibs;
#property (nonatomic, retain) NSMutableArray *nibs;
#property (nonatomic, retain) NSMutableArray *unusedNibs;
then we jump into the .m,
i write all the stuff for the arrays,
nibs = [[NSMutableArray alloc]initWithObjects:#"Question 2", #"Question 3", nil];
self.unusedNibs = nibs;
[nibs release];
Then i also have another class called Question 1, i need to be able to use this array in that class, and be able to change it, but keep the changes on the HowToPlay.m file.
here is why, basically this array loads random NIB files, and then deletes them from the array when they have been used.
in Question 1.m here is what im doing to use the array
random = arc4random() % [self.unusedNibs count];
NSString *nibName = [self.unusedNibs objectAtIndex:random];
[self.unusedNibs removeObjectAtIndex:random];
if (nibName == #"Question 3") {
Question_3 *Q3 = [[Question_3 alloc] initWithNibName:#"Question 3" bundle:nil];
Q3.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:Q3 animated:YES];
[Q3 release];
}
if (nibName == #"Question 2") {
Question_2 *Q2 = [[Question_2 alloc] initWithNibName:#"Question 2" bundle:nil];
Q2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:Q2 animated:YES];
[Q2 release];
}
This all seems to work fine, but the problem im having is it seems that objects in the array are not getting deleted, even though this line runs
[self.unusedNibs removeObjectAtIndex:random];
I haved tried making it
[HowToPlay.unusedNibs removeObjectAtIndex:random];
I get a error saying expected '.' before '.' token
It seems to me that i have access to read the array, but not to change it. any way to fix this so i can change the array? thanks
UPDATE:
here is the whole HowToPlay.h file contents:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
int score;
int usedQ1;
int usedQ2;
int usedQ3;
NSMutableArray *nibs;
NSMutableArray *unusedNibs;
#interface HowToPlay : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
UIPickerView *selectType;
NSMutableArray *selectArray;
AVAudioPlayer *audioPlayer;
UIActivityIndicatorView *progress;
UIButton *worldButton;
UIButton *politicsButton;
UIButton *starButton;
}
#property (nonatomic, retain) NSMutableArray *nibs;
#property (nonatomic, retain) NSMutableArray *unusedNibs;
#property (nonatomic, retain) IBOutlet UIButton *worldButton;
#property (nonatomic, retain) IBOutlet UIButton *politicsButton;
#property (nonatomic, retain) IBOutlet UIButton *starButton;
#property (nonatomic, retain) IBOutlet UIPickerView *selectType;
#property (nonatomic) int usedQ1;
#property (nonatomic) int usedQ2;
#property (nonatomic) int usedQ3;
#property (readwrite) int score;
-(IBAction)World:(id)sender;
- (IBAction)Politics:(id)sender;
-(IBAction)Stars:(id)sender;
#end
#import "MainViewController.h"
#import "Question 1.h"
#import "Question 2.h"
#import "Question 3.h"
I import after because otherwise i get errors
Also I have the array set up on theViewDidLoad part of HowToPlay, is this a bad idea?
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
NSURL *click = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/click.wav", [[NSBundle mainBundle] resourcePath]]];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:click error:nil];
audioPlayer.numberOfLoops = 1;
progress = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
progress.frame = CGRectMake(0.0, 0.0, 30.0, 30.0);
progress.center = self.view.center;
[self.view addSubview: progress];
usedQ1 = 0;
usedQ2 = 0;
usedQ3 = 0;
selectArray = [[NSMutableArray alloc]init];
[selectArray addObject:#"World"];
[selectArray addObject:#"Politics"];
[selectArray addObject:#"Stars"];
score = 0;
nibs = [[NSMutableArray alloc]initWithObjects:#"Question 2", #"Question 3", nil];
self.unusedNibs = nibs;
[nibs release];
}
How do you check if objects are actually deleted? Please post some more code as the way you remove objects from unusedNibs seems to be fine. As per this code:
[self.unusedNibs removeObjectAtIndex:random];
and this code
[HowToPlay.unusedNibs removeObjectAtIndex:random];
The reason why you're getting this error is because you're trying to access unusedNibs using a class name "HowToPlay" instead of its instance "self".
A couple of things: first, to call properties like unusedNibs in HowToPlay it looks like you are calling the class and not an instance. You need to create a HowToPlay object and assign it to a property in your Question1 object so the question one Object has something to call to. Question1 should not call 'self' for unusedNibs since it does not own it.
With what you are doing it might make more sense to put the function figuring out the next random controller in the HowToPlay class. That way your question view controllers could just ask it to return which controller is next without having to duplicate that code across every question controller.

NSMutableArray initWithObjects Not Working

Ey guys, I am having some problems adding NSURLs to an array and looping through them. Here are the relevant portions of my code:
RSS_ReaderAppDelegate.h:
#interface RSS_ReaderAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
NSDictionary *RSSFeeds;
NSMutableArray *RSSFeedURLs;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) NSDictionary *RSSFeeds;
#property (nonatomic, retain) NSMutableArray *RSSFeedURLs;
RSS_ReaderAppDelegate.m:
#implementation RSS_ReaderAppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize RSSFeeds, RSSFeedURLs;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSURL *url1 = [[NSURL alloc] initWithString:#"http://<some url>"]; //real URL has been hidden
NSURL *url2 = [[NSURL alloc] initWithString:#"http://<some other url>"]; //real URL has been hidden
[RSSFeedURLs initWithObjects: url1, url2, nil];
[url1 release];
[url2 release];
for (NSURL *url in RSSFeedURLs) { //jumps right over this for loop
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] init];
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error(s) encountered");
}//for
// Add the navigation controller's view to the window and display.
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
So [RSSFeedURLs initWithObjects: url1, url2, nil]; doesn't seem to actually do anything as when I run the debugger and type "po RSSFeedsURLs" it reports: "Cannot access memory at address 0x0", and thus the for loop is never entered. I have no idea why this is so, can anyone shed some light on this situation for me? Thanks in advance.
you want:
RSSFeedURLs = [[NSMutableArray alloc] initWithObjects: url1, url2, nil];
but you should want:
rssFeedURLs = [[NSMutableArray alloc] initWithObjects: url1, url2, nil];
Variables starting with capital letters lead to much confusion.