Objective-C NSKeyedUnarchiver unloading - objective-c

In some AppDelegate class I have property NSDictionary *dict;
In applicationDidFinishLaunching i'm loading it like:
dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:
#"/Users/username/Desktop/storage"];
Then, I have Outlet for button click. But inside click-action handler I could not access to dict's elements. What am I doing wrong?
EDIT:
here's .h-file:
#import <Cocoa/Cocoa.h>
#interface tttAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSDictionary *dict;
}
#property (assign) IBOutlet NSWindow *window;
- (IBAction)click:(id)sender;
#end
and .m-file:
#import "tttAppDelegate.h"
#implementation tttAppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:#"/some/storage"];
NSLog(#">>>>>>> %#", [dict valueForKey:#"test"]); // ok
}
- (IBAction)click:(id)sender {
NSLog(#">>>>>>> %#", [dict valueForKey:#"test"]); // fail
}
#end

You should use property accessors instead of directly accessing your instance variables:
In your .h file:
#interface tttAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSDictionary *dict;
}
#property (assign) IBOutlet NSWindow *window;
#property (nonatomic, retain) NSDictionary *dict;
- (IBAction)click:(id)sender;
#end
In your .m:
#implementation tttAppDelegate
#synthesize window;
#synthesize dict;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:#"/some/storage"];
NSLog(#">>>>>>> %#", [self.dict valueForKey:#"test"]); // ok
}
- (IBAction)click:(id)sender {
NSLog(#">>>>>>> %#", [self.dict valueForKey:#"test"]); // fail
}
#end
There are several reasons for doing this, but the most important in this case is that that way the accessor methods can handle memory management of the instance variable.

Related

Not Properly Passing Data Between Views

I'm trying to send text generated by the user from the AuthenticationViewController to MainProfileViewController. I'm not receiving an error report. The label just doesn't even appear in the MainProfileViewController. The outlets are correctly hooked up. Thanks for the help!
#import <UIKit/UIKit.h>
#class MainProfileViewController;
#interface AuthenticationViewController : UIViewController
{
MainProfileViewController *mainProfileViewController;
}
#property (retain, nonatomic) IBOutlet UITextField *usernameTextField;
#end
#import "AuthenticationViewController.h"
#import "MainProfileViewController.h"
#interface AuthenticationViewController ()
#end
#implementation AuthenticationViewController
#synthesize usernameTextField;
- (IBAction)createAccount: (id)sender {
{
mainProfileViewController = [[MainProfileViewController alloc] init];
mainProfileViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
mainProfileViewController.userText.text = usernameTextField.text;
[self presentViewController:mainProfileViewController animated:YES completion:nil];
}
}
#end
#import <UIKit/UIKit.h>
#import "AuthenticationViewController.h"
#interface MainProfileViewController : UIViewController
{
UITextField *userText;
}
#property (retain, nonatomic) IBOutlet UILabel *resultLabel;
#property (retain, nonatomic) IBOutlet UITextField *userText;
#property (retain, nonatomic) NSString *textPass;
#end
#import "MainProfileViewController.h"
#import "AuthenticationViewController.h"
#interface MainProfileViewController ()
#end
#implementation MainProfileViewController
#synthesize resultLabel, userText, textPass;
- (void)viewDidLoad
{
userText.text = textPass;
[super viewDidLoad];
}
#end
OK, there's a few things you're doing wrong.
First off, you're instantiating a local MainProfileViewController instead of instantiating the one that you have an ivar pointing to.
The second thing that you're doing wrong is trying to send over the view from the AuthenticationViewController to the MainProfileViewController. You shouldn't do that. Instead, pass the text itself; otherwise you are just overwriting pointers, and nothing will show up.
- (IBAction)createAccount: (id)sender {
// DON'T CREATE A LOCAL VARIABLE
// MainProfileViewController *controller = [[MainProfileViewController alloc] initWithNibName:#"MainProfileViewController" bundle:nil];
mainProfileViewController = [[MainProfileViewController alloc] initWithNibName:#"MainProfileViewController" bundle:nil];
mainProfileViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
// DON'T TRY SENDING THE VIEW OVER
// mainProfileViewController.userText = usernameTextField;
mainProfileViewController.userText.text = usernameTextField.text;
[self presentViewController:mainProfileViewController animated:YES completion:nil];
}
edit: I suppose it's not required that you have an ivar to the new view controller you want to present... But the point is that you cannot instantiate one, and then set the parameter on the one you did not instantiate (it will be nil).
Check your story board and see if you connected the Outlets properly.
There should be an IBOutlet object in your view controller that you should connect in story board.
Also check if you connected the correct view controller class to the view controller in storyboard
#import <UIKit/UIKit.h>
#class MainProfileViewController;
#interface AuthenticationViewController : UIViewController
{
MainProfileViewController *mainProfileViewController;
}
#property (retain, nonatomic) IBOutlet UITextField *usernameTextField;
#end
#import "AuthenticationViewController.h"
#import "MainProfileViewController.h"
#interface AuthenticationViewController ()
#end
#implementation AuthenticationViewController
#synthesize usernameTextField;
- (IBAction)createAccount: (id)sender {
{
MainProfileViewController *controller = [[MainProfileViewController alloc] initWithNibName:#"MainProfileViewController" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
mainProfileViewController.textpass = usernameTextField.text;
[self presentViewController:controller animated:YES completion:nil];
}
}
#end
#import <UIKit/UIKit.h>
#import "AuthenticationViewController.h"
#interface MainProfileViewController : UIViewController
{
UITextField *userText;
}
#property (retain, nonatomic) IBOutlet UILabel *resultLabel;
#property (retain, nonatomic) IBOutlet UITextField *userText;
#property (retain, nonatomic) NSString *textpass;
#end
#import "MainProfileViewController.h"
#import "AuthenticationViewController.h"
#interface MainProfileViewController ()
#end
#implementation MainProfileViewController
#synthesize resultLabel, userText;
- (void)viewDidLoad {
usertext.text=textpass;
}
#end
You need to change your code on this part...
- (IBAction)createAccount: (id)sender
{
mainProfileViewController = [[MainProfileViewController alloc] init];
mainProfileViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
mainProfileViewController.userText.text = usernameTextField.text;
[self presentViewController:mainProfileViewController animated:YES completion:nil];
}
Happy Coding...

How to run a method from appdelegate after a controller has finished running?

The idea is that I hava a custom view where the user can drag and drop one or more files and the controller is able to save the path of files into an array.
How can I run a method from AppDelegate after the user drops the file in the interface?
I have these files:
AppDelegate.h:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSScrollView *table;
#property (assign) IBOutlet NSWindow *window;
#end
AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
#end
DropView.h:
#import <Cocoa/Cocoa.h>
#interface DropView : NSView <NSDraggingDestination>
#property (assign) IBOutlet NSScrollView *table;
#property NSArray *draggedFilePaths;
#end
DropView.m:
#import "DropView.h"
#implementation DropView
#synthesize draggedFilePaths;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
}
return self;
}
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
return NSDragOperationGeneric;
}
-(NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender{
return NSDragOperationCopy;
}
-(BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender{
return YES;
}
-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender{
NSPasteboard* prb;
prb= [sender draggingPasteboard];
draggedFilePaths = [prb propertyListForType:NSFilenamesPboardType];
return YES;
}
- (void)concludeDragOperation:(id<NSDraggingInfo>)sender{
[self setNeedsDisplay:YES];
NSLog(#"path %#",draggedFilePaths);
[self populateTable];
}
- (void)drawRect:(NSRect)dirtyRect
{
}
-(void)populateTable{
NSLog(#"yes");
}
#end
Import AppDelegate.h into DropView.m, and call the method you want to run from the performDragOperation: method.
-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender{
NSPasteboard* prb;
prb= [sender draggingPasteboard];
draggedFilePaths = [prb propertyListForType:NSFilenamesPboardType];
[(AppDelegate *)[[NSApplication sharedApplication]delegate] doWhatever:draggedFilePaths];
return YES;
}
Where doWhatever: is a method implemented in the app delegate.

Undeclared identifier "isGameCenterAvailable"

Following a book tutorial and seem to run into a snag with the "isGameCenterAvailable" error.
Apparently it is undeclared. Everything else seems to work however so I just need to figure this part out.
Helloworldlayer .m init method
#import <GameKit/GameKit.h>
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper]; gkHelper.delegate = self;
[gkHelper authenticateLocalPlayer];
Class gameKitLocalPlayerClass = NSClassFromString(#"GKLocalPlayer"); bool isLocalPlayerAvailable = (gameKitLocalPlayerClass != nil);
// Test if device is running iOS 4.1 or higher
NSString* reqSysVer = #"4.1";
NSString* currSysVer = [[UIDevice currentDevice] systemVersion]; bool isOSVer41 = ([currSysVer compare:reqSysVer
options:NSNumericSearch] != NSOrderedAscending);
isGameCenterAvailable = (isLocalPlayerAvailable && isOSVer41);
-(void) onLocalPlayerAuthenticationChanged {
[delegate onLocalPlayerAuthenticationChanged];
}
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.authenticated == NO) {
[localPlayer authenticateWithCompletionHandler: ^(NSError* error) {
[self setLastError:error]; }];
}
}
Gamekit.h
#import "cocos2d.h"
#import <GameKit/GameKit.h>
#protocol GameKitHelperProtocol
-(void) onLocalPlayerAuthenticationChanged; -(void) onFriendListReceived: (NSArray*)friends; -(void) onPlayerInfoReceived:(NSArray*)players; #end
#interface GameKitHelper : NSObject {
id<GameKitHelperProtocol> delegate; bool isGameCenterAvailable; NSError* lastError;
}
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
#property (nonatomic, readonly) bool isGameCenterAvailable; #property (nonatomic, readonly) NSError* lastError;
+(GameKitHelper*) sharedGameKitHelper;
// Player authentication, info
-(void) authenticateLocalPlayer;
-(void) getLocalPlayerFriends;
-(void) getPlayerInfo:(NSArray*)players;
#end
helloworld layer.h
#import "GameKitHelper.h"
#interface helloworldlayer : CCLayer <GameKitHelperProtocol>
{
}
gamekithelper. h
#import "cocos2d.h"
#import <GameKit/GameKit.h>
#protocol GameKitHelperProtocol
-(void) onLocalPlayerAuthenticationChanged; -(void) onFriendListReceived:(NSArray*)friends; - (void) onPlayerInfoReceived:(NSArray*)players; #end
#interface GameKitHelper : NSObject {
id<GameKitHelperProtocol> delegate; bool isGameCenterAvailable; NSError* lastError;
}
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
#property (nonatomic, readonly) bool isGameCenterAvailable; #property (nonatomic, readonly) NSError* lastError;
+(GameKitHelper*) sharedGameKitHelper;
// Player authentication, info
-(void) authenticateLocalPlayer;
-(void) getLocalPlayerFriends;
-(void) getPlayerInfo:(NSArray*)players;
#end
The problem is you never actually declare isGameCenterAvailable. To fix this, do this:
//HelloWorldLayer.h
#property (nonatomic) BOOL isGameCenterAvailable;
//HelloWorldLayer.m
#synthesize isGameCenterAvailable = _isGameCenterAvailable;
UPDATE:
To fix the delegate error, try this:
//HelloWorldLayer.h
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
//HelloWorldLayer.m
#synthesize delegate;
Hope this helps!

My delegate action is not called in Cocoa

I have a class which has it's delegate:
#protocol SNIRCControllerDelegate
- (void) serverTalked:(id)data;
#end
#interface SNIRCController : NSObject <NSStreamDelegate> {
id<SNIRCControllerDelegate> delegate;
}
- (void) setDelegate:(id<SNIRCControllerDelegate>)_delegate;
- (void) test;
#end
The implementation:
#implementation SNIRCController
- (void) setDelegate:(id<SNIRCControllerDelegate>)_delegate {
_delegate = delegate;
}
- (void) test {
[delegate serverTalked:#"test"];
}
But for some reason [delegate serverTalked:#"test"]; doesn't calls the delegate :/
This is how I do it on the AppDelegate:
#interface AppDelegate : NSObject <NSApplicationDelegate, NSStreamDelegate, SNIRCControllerDelegate> {
IBOutlet NSTextView *logField;
SNIRCController *ircController;
}
#property (assign) IBOutlet NSWindow *window;
-(void)writeToLog:(NSString*)data;
#end
#implementation AppDelegate
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
ircController = [[SNIRCController alloc] init];
[ircController setDelegate:self];
[ircController test];
}
- (void) serverTalked:(id)data {
NSLog(#"got called :D");
}
-(void)writeToLog:(NSString*)data {
NSAttributedString *stringToAppend = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#\n", data]];
[[logField textStorage] appendAttributedString:stringToAppend];
}
But serverTalked: doesn't gets called :( what I'm doing wrong?
In your implementation of setDelegate:, this:
_delegate = delegate;
should be:
delegate = _delegate;
You got confused and swapped ivar and parameter. The confusion might have been caused by the fact that the underscore prefix is more commonly used for ivars. In your case, it is the parameter that is prefixed with an underscore.

using appDelegate to share data - getting "request for member in __ not in structure or union"

I've got a simple example where i have a delegate that has a string, along with a property to expose it.
myAppDelegate.h
#import <UIKit/UIKit.h>
#interface myAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *rootController;
NSString* myText;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
#property (nonatomic, retain) NSString *myText;
#end
myAppDelegate.m
#import "myAppDelegate.h"
#implementation myAppDelegate
#synthesize window;
#synthesize rootController;
#synthesize myText;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:rootController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[rootController release];
[window release];
[super dealloc];
}
#end
So in my main view controller, I try something like this:
myAppDelegate* ad = (myAppDelegate*)[UIApplication sharedApplication].delegate;
ad.myText = #"blah";
and I get: Request for member 'myText' in something not a structure or union
does anyone know why this is happening?
Have you tried using setter instead of dot notation?
[ad setMyText:#"blah"];