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
Related
I have been trying this for quite sometime now, but I just couldn't be able to post successfully to my server. I have read this, github object mapping overview for the Restkit and, the Gist restKit tutorial.
My Problem
I am trying to post sign in information(nickname,hardwareId,phone model) and get the AccountId from my server. But I am getting this response from the console:
GuessTheImage[6832:70b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AccountsClass 0x8c5cba0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key AccountInfo.'
What I think is the problem
I believe I am messing up the way I store the data right before the mapping part. But I am not sure where exactly.
The JSON that I am trying post should look like this
{
"DeviceType": "sample string 1",
"HardwareId": "sample string 2",
"NickName": "sample string 3",
"AccountId": 4
}
Overview of the program
I created the variables for mapping in the AccountClass. From loginviewcontroller, I get the device type, hardwareId and nickname after the user clicks login button and assign those variables to the variables in AccountClass and map it POST if afterwards.
AccountClass.h
#import <Foundation/Foundation.h>
#interface AccountsClass : NSObject
#property (nonatomic, strong,retain)NSString *DeviceType;
#property (nonatomic,strong)NSNumber *AccountId;
#property (nonatomic,strong) NSString *NickName;
#property (nonatomic,strong) NSNumber *HardwareId;
#end
LoginViewController.h
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController<UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *usernameTextField;
#property (strong, nonatomic) IBOutlet UIButton *submitButton;
#property (nonatomic,readonly) NSUUID *identifierForVendor;
#property(nonatomic, readonly, retain) NSString *model;
#property (nonatomic,readonly,retain)NSString *StoreIdentifierForVendor;
#property (nonatomic,readonly,retain)NSString *StoreTheModel;
- (IBAction)submit:(id)sender;
#property (nonatomic,strong)NSString *nickname;
#end
LoginViewController.m
#import "LoginViewController.h"
#import <RestKit/RestKit.h>
#import "AccountsClass.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize usernameTextField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(dissmissKeyboard)];
[self.view addGestureRecognizer:tap];
[usernameTextField setDelegate:self];
}
-(void)loadPostRequest
{
_StoreIdentifierForVendor = [[[UIDevice currentDevice]identifierForVendor]UUIDString];
_StoreTheModel = [UIDevice currentDevice].model;
_nickname = usernameTextField.text;
AccountsClass *AccountInfo = [[AccountsClass alloc] init];
AccountInfo.NickName = _nickname;
NSNumberFormatter *hardwareIdentification = [[NSNumberFormatter alloc]init];
[hardwareIdentification setNumberStyle:NSNumberFormatterScientificStyle];
NSNumber *hwreID =[hardwareIdentification numberFromString:_StoreIdentifierForVendor];
AccountInfo.HardwareId = hwreID;
AccountInfo.DeviceType =_StoreTheModel;
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[AccountsClass class]];
[responseMapping addAttributeMappingsFromArray:#[#"NickName", #"HardwareId", #"DeviceType",#"AccountId"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *AccountDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping]; // objectClass == NSMutableDictionary
[requestMapping addAttributeMappingsFromArray:#[#"AccountInfo.NickName", #"AccountInfo.HardwareId", #"AccountInfo.DeviceType",#"AccountInfo.AccountId"]];
// For any object of class Article, serialize into an NSMutableDictionary using the given mapping and nest
// under the 'article' key path
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[AccountInfo class] rootKeyPath:nil method:RKRequestMethodAny];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"https://picquiz.azurewebsites.net"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:AccountDescriptor];
// POST to create
[manager postObject:AccountInfo path:#"/Accounts" parameters:nil success:nil failure:nil];
}
-(void)dissmissKeyboard
{
[usernameTextField resignFirstResponder];
}
- (IBAction)submit:(id)sender {
[self loadPostRequest];
}
#end
I will appreciate your help.
Your problem appears to be:
[requestMapping addAttributeMappingsFromArray:#[#"AccountInfo.NickName", #"AccountInfo.HardwareId", #"AccountInfo.DeviceType",#"AccountInfo.AccountId"]];
because the data that you are trying to POST doesn't have nested data like that. It looks like it should be:
[requestMapping addAttributeMappingsFromArray:#[#"NickName", #"HardwareId", #"DeviceType",#"AccountId"]];
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
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;
I have a NSMutableOrderedSet which looks like this:
self.tableViewData = [[NSMutableOrderedSet alloc ]initWithObjects:
#"Red",
#"Blue",
#"Yellow", nil];
I'm using delegate to pass data to AppDelegate:
-(IBAction)add
{
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[delegate setData:self.tableViewData];
}
Here is AppDelegate.h:
#property (nonatomic, strong) NSMutableOrderedSet *data;
and AppDelegate.m:
#synthesize data = _data;
The problem is that the app crashes on this line:
[delegate setData:self.tableViewData];
with no error message in lldb. What is wrong here?
It looks like you are typecasting [UIApplication sharedApplication] to (AppDelegate *).
Try
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
What am I doing wrong? My code crashes when I try to log the array. Here is my class:
#interface ArrayTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
NSArray *array;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) NSArray *array;
-(IBAction)buttonPressed;
#end
#implementation ArrayTestAppDelegate
#synthesize window, array;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
array = [NSArray arrayWithObjects:#"Banana", #"Apple", #"Orange", #"Pear", #"Plum", nil];
[window makeKeyAndVisible];
}
-(IBAction)buttonPressed {
NSLog(#"%#", array);
}
- (void)dealloc {
[window release];
[array release];
[super dealloc];
}
#end
This is a common memory management error in Cocoa. The arrayWithObjects method of the NSArray class returns an autoreleased object. By the time you try to log the array in the buttonPressed method, the array has already been released and you get a crash. The fix is easy:
array = [[NSArray alloc] initWithObjects:#"Banana", #"Plum", nil];
Or:
array = [[NSArray arrayWithObjects:#"Banana", #"Plum", nil] retain];
I guess the first one is better, the retain on the end of the second example is easy to miss. I would suggest that you read some more on memory management in Cocoa.