Encoding and decoding custom objects - ios

I'm having trouble encoding and saving a list of custom objects containing a MKMapItem to NSUserDefaults.
Firstly, I get the selected MKMapItem from an array of MKMapItems used for a tableView and store that in my sharedManager instance. (All the values in sharedManager will be used later to create a custom object).
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get the tapped MKMapItem
MKMapItem *selectedMapItem = self.searchResults[indexPath.row];
// Create a sharedManager instance
MyManager *sharedManager = [MyManager sharedManager];
// Set the workRegion and workLocation in sharedManager
NSLog(#"selectedMapItem: %#", [selectedMapItem name]);
sharedManager.workLocation = selectedMapItem;
// Post a notification to alert the PreviewMapViewController
[[NSNotificationCenter defaultCenter] postNotificationName:#"showAnnotations" object:self.searchResults];
[[NSNotificationCenter defaultCenter] postNotificationName:#"zoomToAnnotation" object:selectedMapItem];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showMap" object:nil];
}
This is the code I use to take the MKMapItem from sharedManager and put it in the custom object I've created:
MyManager *sharedManager = [MyManager sharedManager];
newModel.workLocation = sharedManager.workLocation;
My custom object stores workLocation in its header file with a property as follows:
#property (nonatomic, strong) MKMapItem *workLocation;
This is the implementation file where I encode and decode the workLocation object:
#implementation WorkLocationModel
-(id)init {
// Init self
self = [super init];
if (self)
{
// Setup
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.workLocation forKey:#"workLocation"];
}
-(instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self)
self.workLocation = [coder decodeObjectForKey:#"workLocation"];
return self;
}
#end
My breakpoint set to catch all the exceptions breaks on the encodeObject line.
The error occurs when I add this custom object to a NSMutableArray and then save that array using:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_myObjects] forKey:#"myObjects"];
Exception:
-[MKMapItem encodeWithCoder:]: unrecognized selector sent to instance 0x7f9f14acf400
Can anyone help me with this?
UPDATE:
NSData *workLocationData = [NSKeyedArchiver archivedDataWithRootObject:sharedManager.workLocation];

MKMapItem does not conform to NSCoding or SSecureCoding.
You will need to encode the individual items and re-create a MKMapItem on decode.

Related

How to initialise a VC or Class iOS, ObjectiveC

When a button is clicked at FirstVC, it will pass data and trigger SecondVC using NSNotificationCenter
During initial launch of the app, because SecondVC has not been initialize yet, so data cannot be passed to SecondVC. NSNotificationCenter cannot function properly. Only after SecondVC has been initialize, NSNotificationCenter will function correctly.
So I need to initialise SecondVC somewhere. Will it be at - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions?
Or how do I programatically call the tab of SecondVC.
FirstVC
#import "Search.h"
#import "Classes.h"
#import "MyTabBarController.h"
#interface Search(){
AppDelegate *appDelegate;
CERangeSlider* _rangeSlider;
NSString *sURL, *strResult, *sRemaining, *sStartTime, *sEndTime, *sSelectedLat, *sSelectedLong;
}
#end
#implementation Search
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:sURL forKey:#"theURL"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"toClasses" object:nil userInfo:userInfo];
}
#end
Second VC
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(receiveTestNotification:)
name:#"toClasses"
object:nil];
dtDate = [[NSMutableArray alloc] init]; //=== Mutable array to store the dates generated
self.currentPageIndex = 0;
[self setupSegmentButtons];
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/YYYY"];
sDtDate = [dateFormatter stringFromDate:now];
[self LoadClasses];
}
-(void)viewWillAppear:(BOOL)animated {
//--- Hide the Top Navigation Controller Bar at the current View
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}
//--- Top Navigation Controller reappear on the next VC
-(void)viewDidDisappear:(BOOL)animated{
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
-(void) receiveTestNotification:(NSNotification*)notification
{
if ([notification.name isEqualToString:#"toClasses"])
{
NSDictionary* userInfo = notification.userInfo;
NSLog (#"Successfully received userInfo! %#", userInfo);
NSString* sFromSearch = [NSString stringWithFormat: #"%#", userInfo];
NSLog (#"Successfully received test notification! %#", sFromSearch);
}
}
In my opinion, you don't need to use notification or singleton on this case.
Simply, get SecondViewController from self.tabBarController and call the method.
First VC
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
UINavigationController* secondNav = (UINavigationController*)self.tabBarController.viewControllers[1];
SecondViewController* secondViewController = [secondNav.viewControllers firstObject];
[secondViewController handleString:sURL];
}
Second VC
- (void)handleString:(NSString*)string {
// Do whatever you want with string passed from First VC
}
You added observer in viewDidLoad, so it will not work even you create it before user tap on button and send notification. because observer will not be registered. I advise you not use observer to send data in this case. you can save this data elsewhere and use it when seconVC will load. for example in singleton object.
your Singleton object looks like this:
Interface:
#interface DataManager : NSObject
#property (nonatomic, strong) NSDictionary *userInfo;
+ (DataManager *) getInstance;
#end
Implementation:
#implementation DataManager
+ (DataManager *) getInstance {
static DataManager *appManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
appManager = [[DataManager alloc] init];
});
return appManager;
}
#end
Now you can access this object where you want and you can assured that only one instance is created.
here is your button click method:
- (IBAction)btnSearch:(UIButton *)sender {
self.tabBarController.selectedIndex = 1;
sURL = #"Testing 123";
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:sURL forKey:#"theURL"];
[DataManager getInstance].userInfo = userInfo;
}
and your viewDidLoad in secondVC
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *userInfo = [DataManager getInstance].userInfo;
}

Objective-c calling a method from class method

I am trying to access an instance method from a class method. I am getting this error
+[ActiveVC goToDashBoard]: unrecognized selector sent to class 0x112010
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[ActiveVC goToDashBoard]:
unrecognized selector sent to class 0x112010'
My code
+ (void) removeClosedVisitor:(NSString *) visitorID{
for (NSInteger i = activelist.count - 1; i >= 0 ; i--) {
ActiveItemObject *item = [activelist objectAtIndex:i];
if ([visitorID isEqualToString:item.VisitorId]) {
NSLog(#"Removing Visitor from Active List -- %#", visitorID);
[activelist removeObjectAtIndex:i];
//[self.incommingTable reloadData];
// NSDictionary *activeDictionary = [[NSDictionary alloc] init];
// activeDictionary = [activelist mutableCopy];
//
// [[NSNotificationCenter defaultCenter]
// postNotificationName:#"PassData"
// object:nil
// userInfo:activeDictionary];
[[self class] goToDashBoard];
}
}
}
- (void) goToDashBoard{
NSLog(#"Segue to Dashboard");
UITabBarController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"id_tabView"];
[dvc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentViewController:dvc animated:YES completion:nil];
}
can some one help me to fix this issue . tnx.
You need to create an instance of your class or convert your class to a singleton. For example: [[ActiveVC sharedInstance] goToDashBoard];
Here's how you create a Singleton Class:
First, create a New file and subclass it from NSObject. Name it anything, we will use CommonClass here. Xcode will now generate CommonClass.h and CommonClass.m files for you.
In your CommonClass.h file:
#import <Foundation/Foundation.h>
#interface CommonClass : NSObject {
}
+ (CommonClass *)sharedObject;
#property NSString *commonString;
#end
In your CommonClass.m File:
#import "CommonClass.h"
#implementation CommonClass
+ (CommonClass *)sharedObject {
static CommonClass *sharedClass = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedClass = [[self alloc] init];
});
return sharedClass;
}
- (id)init {
if (self = [super init]) {
self.commonString = #"this is string";
}
return self;
}
#end
If you want to call instance method then you will need an instance variable so create instance variable of this class and call it.
Make goToDashBoard a class method. Since you are not creating any instance here, if it is not a class method then it can't be executed.
+ (void) goToDashBoard
Do you actually have an instance anywhere? If not you will have to create one:
[self.sharedInstance goToDashBoard]
[[self alloc] init] goToDashBoard]
I assume you do have an instance, because its looks like its a view controller. In which case I suggest you pass the instance into the static method.
+ (void) removeClosedVisitor:(NSString *) visitorID viewController: (xxx) viewController {

How do i pass info from loginViewFetchedUserInfo: to multiple views at once

Hi i am trying to pass the user.id and user.name from loginViewFetchedUserInfo: to my menuViewController, profileViewController and settingViewController so far i have sent the info to profileViewController with:
// this method will be called when the user information has been fetched
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user
{
// self.profilePictureView.profileID = user.id;
//self.FBProfilePicture.profileID = user.id;
_profilePicture = user;
_FBNameString = user.name;
NSLog(#"%#, name from Login", _FBNameString);
[self pushViewController:user.name andProfilePicture:_profilePicture];
}
- (void)pushViewController:(NSString *)userName andProfilePicture:(id<FBGraphUser>)profilePicture
{
// MenuViewController *menu = [self.storyboard instantiateViewControllerWithIdentifier:#"MenuViewController"];
// [menu setFBName:userName];
// [menu setFBProfilePic:profilePicture];
//
// SettingViewController *setting = [self.storyboard instantiateViewControllerWithIdentifier:#"SettingViewController"];
// [setting setFBName:userName];
// [setting setFBProfilePic:profilePicture];
// NSLog(#"%#",profilePicture);
// [self.navigationController pushViewController:controller animated:NO];
}
and i can only receive the info in the profileViewController and not the other i have put setters and getters i'm using protocols but i'm not able to get it to another viewController
In general you method should be like this.(you may need to tweak as per requirement)
// this method will be called when the user information has been fetched
-(void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user{
// self.profilePictureView.profileID = user.id;
//self.FBProfilePicture.profileID = user.id;
_profilePicture = user.picture;//assuming you may be having picture property for object user
_FBNameString = user.name;
NSLog(#"%#, name from Login", _FBNameString);
//POST NOTIFICATION with desire object here its "user"
[[NSNotificationCenter defaultCenter] postNotificationName:#"POSTLOGININFO" object:user];
//uncomment if you want this, ...depends on you
//[self pushViewController:user.name andProfilePicture:_profilePicture];
}
Now update init method of your menuViewController.m, profileViewController.m and settingViewController.m class like below
-(id) init
{
self = [super init];
if (!self)
return nil;
//Your custom code
//get registered for POSTLOGININFO notification so that selector method get called when you post notification with name POSTLOGININFO
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(gotLoginInfo:)
name:#"POSTLOGININFO"
object:nil];
return self;
}
Add new method gotLoginInfo: to each of your menuViewController.m, profileViewController.m and settingViewController.m
-(void)gotLoginInfo:(NSNotification *)notification{
//Assuming FBGraphUser class have all required properties
FBGraphUser *user = (FBGraphUser *)[notification object];
// save user.id and user.name to your class local variable
NSLog(#"UserID::%# and username::%#",user.id,user.name);
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"POSTLOGININFO" object:nil];
}
remove notification observer once you are done by using
"[[NSNotificationCenter defaultCenter] removeObserver:self name:#"POSTLOGININFO" object:nil];". Also be sure to have valid objects of your class menuViewController, profileViewController and settingViewController before loginViewFetchedUserInfo: get called
You can use NSNotification.
Example
There is a method named myTestNotificationReceived which is implemented in myClassA. Now I want to call this method from another class myClassB. Below is the code how I can do this using NSNotificationCenter.
#implementation myClassA
- (void) dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myTestNotificationReceived:)
name:#"myTestNotification"
object:nil];
return self;
}
- (void) myTestNotificationReceived:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"myTestNotification"])
NSLog (#"Notification is successfully received!");
}
#end
Now I want to call the method myTestNotification from myClassB.
#implementation myClassB
- (void) dealloc{
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
return self;
}
- (void) myMethod
{
// All instances of myClassA will be notified
[[NSNotificationCenter defaultCenter]
postNotificationName:#"myTestNotification"
object:self];
}
#end
Now you can add as many observer in your different classes.

UITableView has Empty Rows

I'm having a problem with RSS feeds in a table view in an iOS app. I originally tested the RSS feed in it's project with the table view as the root view. I'm trying to get the same functionality in a different project but the table view that displays the list of articles from the RSS feed is blank. The code for the table view in the new project is the same. The only different is that I have a different root view controller that has a bunch of buttons. One button is supposed to go to that table view and it does but the rows are empty. I'm thinking this may be an issue with how the root view controller is set up since I know the table view is populated when that code is run by itself. Here are the AppDelegate files where it sets the root view controller.
//
// KFBAppDelegate.h
// KFBNewsroom
//
// Created by KFB on 10/15/12.
// Copyright (c) 2012 com.kfb. All rights reserved.
//
#import <UIKit/UIKit.h>
#class KFBViewController;
#interface KFBAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) KFBViewController *viewController;
#end
//
// KFBAppDelegate.m
// KFBNewsroom
//
// Created by KFB on 10/15/12.
// Copyright (c) 2012 com.kfb. All rights reserved.
//
#import "KFBAppDelegate.h"
#import "KFBViewController.h"
#import "ListViewController.h"
#import "WebViewController.h"
#import "ActionAlertsViewController.h"
#import "MarketUpdatesViewController.h"
#implementation KFBAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[KFBViewController alloc] initWithNibName:#"KFBViewController" bundle:nil];
ListViewController *lvc = [[ListViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[lvc setWebViewController:wvc];
ActionAlertsViewController *avc = [[ActionAlertsViewController alloc]initWithStyle:UITableViewStylePlain];
[avc setWebViewController:wvc];
MarketUpdatesViewController *mvc = [[MarketUpdatesViewController alloc]initWithStyle:UITableViewStylePlain];
[mvc setWebViewController:wvc];
self.window.rootViewController = self.viewController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
//
// ListViewController.h
// Nerdfeed
//
// Created by KFB on 10/16/12.
// Copyright (c) 2012 com.kfb. All rights reserved.
//
#import <Foundation/Foundation.h>
// #interface ListViewController : NSObject
// a forward declaration; we'll import the header in the .m
#class RSSChannel;
#class WebViewController;
#interface ListViewController : UITableViewController
<NSXMLParserDelegate>
{
NSURLConnection *connection;
NSMutableData *xmlData;
RSSChannel *channel;
}
#property (nonatomic, strong)WebViewController *webViewController;
- (void)fetchEntries;
#end
//
// ListViewController.m
// Nerdfeed
//
// Created by KFB on 10/16/12.
// Copyright (c) 2012 com.kfb. All rights reserved.
//
#import "ListViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#implementation ListViewController
#synthesize webViewController;
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"%# found a %# element", self, elementName);
if ([elementName isEqual:#"channel"])
{
// If the parser saw a channel, create new instance, store in our ivar
channel = [[RSSChannel alloc]init];
// Give the channel object a pointer back to ourselves for later
[channel setParentParserDelegate:self];
// Set the parser's delegate to the channel object
[parser setDelegate:channel];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return 0;
return [[channel items]count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
}
RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];
[[cell textLabel]setText:[item title]];
return cell;
}
- (void)fetchEntries
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc]init];
// Construct a URL that will ask the service for what you want -
// note we can concatenate literal strings together on multiple lines in this way - this results in a single NSString instance
NSURL *url = [NSURL URLWithString:#"http://kyfbnewsroom.com/category/public- affairs/feed"];
// Put that URL into an NSURLRequest
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
[self fetchEntries];
}
return self;
}
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
/* We are just checking to make sure we are getting the XML
NSString *xmlCheck = [[NSString alloc]initWithData:xmlData encoding:NSUTF8StringEncoding];
NSLog(#"xmlCheck = %#", xmlCheck);*/
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];
// Give it a delegate - ignore the warning here for now
[parser setDelegate:self];
//Tell it to start parsing - the document will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Reload the table.. for now, the table will be empty
[[self tableView]reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
connection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view with this error displayed
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Push the web view controller onto the navigation stack - this implicitly creates the web view controller's view the first time through
[[self navigationController]pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView]loadRequest:req];
// Set the title of the web view controller's navigation item
[[webViewController navigationItem]setTitle:[entry title]];
}
#end
Your ListViewController class must inherit from UITableViewController
Edit: Sorry I didn't see it, just add the delegate & dataSource
#interface ListViewController : UITableViewController
<NSXMLParserDelegate, UITableViewDelegate, UITableViewDataSource>
Did you add:
-(void)viewDidLoad {
[super viewDidLoad];
[tableView setDelegate: self];
[tableView setDataSource: self];
}
On implementation of ListViewController (Like after #synthesize webViewController;
)?
Make sure you set up the UITableView DataSource so that you can actually display rows. You'll probably need to set the delegate too.
EDIT:
You're still not setting the UITableView delegate or datasource. You need to do that so that the UITableView knows where to get data from. I think the best place for you to put that is in your ListViewController's viewDidLoad method
-(void)viewDidLoad {
[super viewDidLoad];
[tableView setDelegate: self];
[tableView setDataSource: self];
}
You'll also need to add the UITableViewDelegate and UITableViewDataSource protocols to ListViewController.
EDIT 2:
Make sure you're adding the UITableViewDataSource and UITableViewDelegate protocols to ListViewController
#interface ListViewController : UITableViewController
<NSXMLParserDelegate, UITableViewDelegate, UITableViewDataSource>
Also, make sure the viewDidLoad method above is in the ListViewController class. All UITableViewControllers have a tableView property that holds the actual UITableView.
Try to remove this line from ListViewController.h
#property (nonatomic, retain) UITableView *tableView;
Then replace your - (void) viewDidLoad in ListViewController.m by this code:
- (void) viewDidLoad
{
[super viewDidLoad];
[self.tableView setDelegate: self];
[self.tableView setDataSource:self];
}

Decoder crashing through a bluetooth connection

I have an object that I want to send to another device via bluetooth. I have successfully setup the bluetooth connection and transferred an encoded NSString; however, I haven't figured out how to use the archiving and encoding tools correctly to send an Object.
I want to send the object defined below called ChatMessage. It implements the NSCoding delegate methods initWithCoder and encodeWithCoder as seen below.
In the second code snippet, I have the code for sending and receiving the data i.e. the methods that result in the de-encoder being called.
It keeps crashing on the last line of the decode method. I've been struggling to figure it out what is going wrong. Any help would be greatly appreciated!
#interface ChatMessage : NSObject <NSCoding> {
NSString *sender;
NSString *message;
}
#property (nonatomic, retain) NSString *sender;
#property (nonatomic, retain) NSString *message;
#end
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:sender forKey:#"sender"];
[coder encodeObject:message forKey:#"message"];
}
- (id)initWithCoder:(NSCoder *)coder {
sender = [[coder decodeObjectForKey:#"sender"] retain];
message = [[coder decodeObjectForKey:#"message"] retain];
return self;
}
In my View, the protocol for the PeerPicker Delegate functions.
- (void) receiveData:(NSData *)data
fromPeer:(NSString *)peer
inSession:(GKSession *)session
context:(void *)context {
ChatMessage *aMsg = [[ChatMessage alloc] init];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
initForReadingWithData:data];
#try {
aMsg = [unarchiver decodeObjectForKey:#"myMessage"];
}
#catch (NSException *exception) {
NSLog(#"Error: %#", exception);
}
#finally {
}
if (!messages) messages = [[NSMutableArray alloc] init];
[messages addObject:aMsg];
// reload the table
[messageList reloadData];
[unarchiver finishDecoding];
[unarchiver release];
[data release];
}
--- The code was crashing because I had
[data release];
I found this using the instruments tool.

Resources