TouchDB saves the attachment but does not save the property - objective-c

I found that my CouchModel (TSCAssetUploadDO) saves the attachment but does not save the property.
TSCAssetUploadDO *assetDO = [[TSCAssetUploadDO alloc] initWithNewDocumentInDatabase: _localAssetUploadDatabase];
NSData *data = UIImageJPEGRepresentation(contact.avatar, 1.0); // may need to resize.
NSString *attachmentName = [docID stringByAppendingString:#".jpg"];
[assetDO createAttachmentWithName:attachmentName type:#"image/jpeg" body:data];
assetDO.relatedDocID = docID;
assetDO.docType = #"contact";
RESTOperation *op2 = [assetDO save];
//[op2 wait]; originally thought that making it sync may work
[op2 onCompletion:^{
if (op2.error) NSLog(#"ERROR [TOUCHDB] %#", op2.error);
else
{
NSLog(#"YES! it saved");
}
if (completionBlock)
{
completionBlock(op2.error, contact);
}
//[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDataUpdated object:nil];
}];
This is resulting to a document like this ( with saved attachment, no property like docType and relatedDocID though )
{
"_id": "D50ED630-34ED-4A02-A9C8-204E79A0648B",
"_rev": "1-b0ce9eaa1fb2f86dc9ae619e27ffe1ea",
"_attachments": {
"QSPNGC665.jpg": {
"content_type": "image/jpeg",
"revpos": 1,
"digest": "md5-u9V0rgoSRN5cUW2T3xh0hw==",
"length": 117500,
"stub": true
}
}
}
Below is the CouchModel that I just used.
#interface TSCAssetUploadDO: CouchModel
#property(nonatomic,retain) NSString *relatedDocID;
#property(nonatomic,retain) NSString *docType;//entity or contact
#property bool *toProcess;
#property (retain) NSDate* created_at;
#end
#implementation TSCAssetUploadDO
- (NSDictionary*) propertiesToSave {
// Initialize created_at the first time the document is saved:
if (self.created_at == nil)
self.created_at = [NSDate date];
return [super propertiesToSave];
}
#end
Is there anything that I did wrong?

Solved my issue. need to add #dynamic
#implementation TSCAssetUploadDO
#dynamic relatedDocID, docType, toProcess, created_at;
<... rest of the code >
#end

Related

Getting 'unrecognised selector' from NSNotificationCenter

I'm trying to implement an observer in the NSNotificationCenter. Instead of using self as the observer I want to create a little object that does it:
typedef void (^ErrorCallback)(NSError*);
typedef void (^SuccessCallback)();
typedef void (^ReplicationChanged) (NSNotification*);
#interface SyncParams : NSObject
#property (copy) ErrorCallback errorCallback;
#property (copy) SuccessCallback successCallback;
#property (copy) ReplicationChanged replicationChanged;//this used to observe
- (void)replicationChanged:(NSNotification*)notification;
#end
#implementation SyncParams
#end
Then later I create an instance of the observer:
SyncParams* params = [SyncParams alloc];
params.replicationChanged = ^(NSNotification* notification) {
//do stuff here
};
And finally add it to the NSNotificationCenter:
[[NSNotificationCenter defaultCenter] addObserver: params
selector: #selector(replicationChanged:)
name: kCBLReplicationChangeNotification
object: replicationObject];
But I get this error: Exception '-[SyncParams replicationChanged:]: unrecognized selector sent to instance 0x7ff945c049a0' was thrown
I'm very new to objective-c! Any pointers?
Yes and no, I ended up with the following:
[[NSNotificationCenter defaultCenter] addObserverForName:kCBLReplicationChangeNotification object:repl queue:nil usingBlock:^(NSNotification *notification) {
NSString *status;
if (repl.status == kCBLReplicationActive) {
NSLog(#"Repication in progress");
status = #"in-progrss";
} else if (repl.status == kCBLReplicationOffline) {
NSLog(#"Sync in offline");
status = #"offline";
} else if (repl.status == kCBLReplicationStopped) {
NSLog(#"Sync in stopped");
status = #"stopped";
} else if (repl.status == kCBLReplicationIdle) {
NSLog(#"Sync in idle");
status = #"idle";
}
NSError *error = repl.lastError;
if(error) {
status = #"error";
NSLog(#"replication error %#", error.code);
}
NSDictionary *dictionary = #{
#"type": type,
#"changesCount": #(repl.changesCount),
#"completedChangesCount": #(repl.completedChangesCount),
#"running": #(repl.running),
#"status": status,
#"suspended": #(repl.suspended),
};
[self sendEventWithName:#"replicationChanged" body:dictionary];
}];
I only ever get one callback though, when it starts up.

Custom Object becoming _NSCFString upon entry into NSMutableArray

I'm having issues placing a custom object (WSWCMPost) into an NSMutableArray and then accessing the data stored in it later. Below is the relevant code.
Here is "WSWCMPost.h"
#import <Foundation/Foundation.h>
#interface WSWCMPost : NSObject
{
NSString *postBody;
NSString *postTitle;
NSString *postID;
}
#property (nonatomic, retain) NSString *postBody, *postTitle, *postID;
- init;
- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title;
- (NSString*)postBody;
- (NSString*)postTitle;
- (NSString*)postID;
Here is "WSWCMPost.m"
#import "WSWCMPost.h"
#implementation WSWCMPost
#synthesize postBody, postTitle, postID;
- (id)init {
self = [super init];
if(self) {
postID = #"none";
postBody = #"none";
postTitle = #"none";
}
}
- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title {
postTitle = title;
postID = ID;
postBody = body;
}
#end
And here is the "viewDidLoad" method that is causing my issues
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (WSWCMDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
// getting an NSString
NSLog(#"Pulling saved blogs...");
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:#"wswcmt1"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
_objects = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
_objects = [[NSMutableArray alloc] init];
}
NSLog(#"Pulled saved blogs...");
NSLog(!_objects ? #"Yes" : #"No");
#try {
NSLog(#"_objects description: %#",[_objects description]);
NSLog(#"_objects[0] postID: %#",[[_objects objectAtIndex:0] postID]);
}
#catch (NSException *exception) {
NSLog(#"Caught exception %#", exception);
NSLog(#"Objects doesnt exist, allocating memory...");
_objects = [[NSMutableArray alloc] init];
WSWCMPost *testPost = [[WSWCMPost alloc] initWithID:#"noID" AndBody:#"noBody" AndTitle:#"noTitle"];
[_objects insertObject:testPost atIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_objects] forKey:#"wswcmt1"];
}
if (!_objects ) {
NSLog(#"Objects doesnt exist...");
_objects = [[NSMutableArray alloc] init];
WSWCMPost *testPost = [[WSWCMPost alloc] initWithID:#"dne" AndBody:#"Dne" AndTitle:#"DNe"];
[_objects insertObject:testPost atIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_objects] forKey:#"wswcmt"];
}
[self refreshButton:nil];
}
And finally, here is the output
2012-06-25 22:39:49.345 WSWCM[4406:907] Pulling saved blogs...
2012-06-25 22:39:49.352 WSWCM[4406:907] Pulled saved blogs...
2012-06-25 22:39:49.355 WSWCM[4406:907] Yes
2012-06-25 22:39:49.356 WSWCM[4406:907] _objects description: (null)
2012-06-25 22:39:49.358 WSWCM[4406:907] _objects[0] postID: (null)
2012-06-25 22:39:49.360 WSWCM[4406:907] Objects doesnt exist...
2012-06-25 22:39:49.363 WSWCM[4406:907] Refresh Triggered...
I think that is all of the relevant code. If i forgot anything let me know please. This issue has been bothering me for hours...
While I'm not positive why it's giving you NSStrings instead of just blowing up normally, the problem seems to stem from the fact that your custom class, WSWCMPost, does not conform to the NSCoding protocol. Make sure that your custom objects implement this protocol if you want to store them in NSUserDefaults, since it doesn't know how to serialize the data otherwise.
To be more exact, you'll have to add these methods to your class implementation:
- (id)initWithCoder:(NSCoder *)coder {
self = [self initWithID:[coder decodeObjectForKey:#"id"] AndBody:[coder decodeObjectForKey:#"body"] AndTitle:[coder decodeObjectForKey:#"title"]];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[encoder encodeObject:postID forKey:#"id"];
[encoder encodeObject:postBody forKey:#"body"];
[encoder encodeObject:postTitle forKey:#"title"];
}
This will allow the data to be serialized by NSCoder. Once you've done this, you should clear all the information currently stored by NSUserDefaults to make sure that it doesn't contain any more NSStrings, but then everything should work properly. Of course, you'll have to update these two methods if you change the data stored by your WSWCMPost object.
Another thing to mention, you're having collisions with your getters/setters and their respective instance variables. So your implementation is:
interface
#interface WSWCMPost : NSObject
{
NSString *postBody; // don't need to do these anymore for properties
NSString *postTitle;
NSString *postID;
}
#property (nonatomic, retain) NSString *postBody, *postTitle, *postID;
implementation
#implementation WSWCMPost
#synthesize postBody, postTitle, postID;
- (id)init {
self = [super init];
if(self) {
postID = #"none"; // not prefixing your variables with 'self' so they are not getting retained
postBody = #"none";
postTitle = #"none";
}
}
#end
Here's how you should be writing those out:
interface
/** NOTE: No need to specify your instance variables here anymore, just the properties */
#interface WSWCMPost : NSObject
#property (nonatomic, retain) NSString *postID;
#property (nonatomic, retain) NSString *postTitle;
#property (nonatomic, retain) NSString *postBody;
implementation
#implementation WSWCMPost
/** Now you specify the corresponding instance variable name alongside the property name */
#synthesize postBody=_postBody, postTitle=_postTitle, postID=_postID;
- (id)init {
self = [super init];
if(self) {
self.postID = #"none"; //getting retained
self.postBody = #"none";
self.postTitle = #"none";
}
}
That would definitely cause data to be released too soon.
So the previous way you could type in self.postID or postID and the compiler wouldn't complain. The difference is when you type postID it is actually setting the member variable and not retaining it... where self.postID will release whatever it is currently set to and retain the new value if it's different.
By declaring your properties the new way, you have to either call the setter as self.postID or set the underlying instance variable as _postID. A lot of early iPhone books had you bang out properties that way and it just ends up causing all sorts of memory issues.
Hope this helps!
UPDATE!!!
You forgot to return self in your constructor ;) I bet that's it
- (id)init {
self = [super init];
if(self) {
self.postID = #"none"; //getting retained
self.postBody = #"none";
self.postTitle = #"none";
}
return self; // THIS IS WHY, you're constructor doesn't return an instance of the class... add this please
}
- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title {
if(( self = [super init] ))
{
self.postTitle = title;
self.postID = ID;
self.postBody = body;
}
return self;
}
Your output definitely shows what was wrong in your code.
2012-06-25 21:51:07.691 WSWCM[4049:907] -[__NSCFString postID]: unrecognized selector sent to instance 0x1d003e80
2012-06-25 21:51:07.696 WSWCM[4049:907] Caught exception -[__NSCFString postID]: unrecognized selector sent to instance 0x1d003e80
These two lines tell you that NSString object does not recognize selector postID. This hint should be enough to find out where you need to see in depth.
See this Storing custom objects in an NSMutableArray in NSUserDefaults for more information.

cannot access mutable array in singleton

singleton.h
#import <Foundation/Foundation.h>
#interface CrestronControllerValues : NSObject {
NSString* ipAddress;
NSString* portNumber;
NSString* phoneAddress;
NSString* cameleonVersion;
NSString* systemName;
NSString* iPID;
NSString* systemFeedBackName;
NSString* dJoinConnectedFB;
NSString* dJoinLow;
NSString* dJoinHigh;
NSString* aJoinLow;
NSString* aJoinHigh;
NSString* sJoinLow;
NSString* sJoinHigh;
NSMutableArray *currentPhonebookEntriesTelepresence;
NSMutableArray *currentPhonebookEntriesVideoChat;
NSMutableArray *currentPhonebookEntriesAudioChat;
}
#property (nonatomic, retain) NSString* ipAddress;
#property (nonatomic, retain) NSString* portNumber;
#property (nonatomic, retain) NSString* phoneAddress;
#property (nonatomic, retain) NSString* cameleonVersion;
#property (nonatomic, retain) NSMutableArray *currentPhonebookEntriesTelepresence;
#property (nonatomic, retain) NSMutableArray *currentPhonebookEntriesVideoChat;
#property (nonatomic, retain) NSMutableArray *currentPhonebookEntriesAudioChat;
#property (nonatomic, retain) NSString* systemName;
#property (nonatomic, retain) NSString* iPID;
#property (nonatomic, retain) NSString* systemFeedBackName;
#property (nonatomic, retain) NSString* dJoinConnectedFB;
#property (nonatomic, retain) NSString* dJoinLow;
#property (nonatomic, retain) NSString* dJoinHigh;
#property (nonatomic, retain) NSString* aJoinLow;
#property (nonatomic, retain) NSString* aJoinHigh;
#property (nonatomic, retain) NSString* sJoinLow;
#property (nonatomic, retain) NSString* sJoinHigh;
+ (id)sharedManager;
#end
i have my singleton.m:
static CrestronControllerValues *sharedMyManager= nil;
#implementation CrestronControllerValues
#synthesize ipAddress, portNumber ,systemName, iPID, systemFeedBackName, dJoinConnectedFB, dJoinLow, dJoinHigh, aJoinLow, aJoinHigh, sJoinLow, sJoinHigh, cameleonVersion, currentPhonebookEntriesAudioChat, currentPhonebookEntriesTelepresence, currentPhonebookEntriesVideoChat, phoneAddress;
+(CrestronControllerValues*)sharedManager
{
#synchronized(self) {
if(!sharedMyManager) {
sharedMyManager = [CrestronControllerValues alloc];
sharedMyManager = [sharedMyManager init];
}
}
}
+(id)alloc
{
#synchronized(self)
{
NSAssert(sharedMyManager == nil, #"Attempted to allocate a second instance of a singleton.");
sharedMyManager = [super alloc];
return sharedMyManager;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
self.ipAddress = #"10.8.40.64";
self.portNumber = 41794;
self.systemName = #"";
self.iPID = 3;
self.cameleonVersion = nil;
self.currentPhonebookEntriesAudioChat = [[NSMutableArray alloc]initWithObjects:nil];
self.currentPhonebookEntriesTelepresence = [[NSMutableArray alloc]initWithObjects:nil];
self.currentPhonebookEntriesVideoChat = [[NSMutableArray alloc]initWithObjects:nil];
self.phoneAddress = nil;
self.systemFeedBackName = #"";
self.dJoinConnectedFB = 5000;
self.dJoinLow = 1;
self.dJoinHigh = 1000;
self.aJoinLow = 1;
self.aJoinHigh = 1000;
self.sJoinLow = 1;
self.sJoinHigh = 1000;
}
return self;
}
return self;
}
-(void)setPhoneAddress:(NSString *)phoneaddress
{
#synchronized(self) {
if (phoneAddress != phoneaddress)
{
[phoneAddress release];
phoneAddress = [phoneaddress retain];
}
}
}
-(NSString*)getPhoneAddress
{
return phoneAddress;
}
-(void)setCurrentPhonebookEntriesAudioChat:(NSMutableArray *)entries
{
#synchronized(self) {
if (currentPhonebookEntriesAudioChat != entries)
{
[currentPhonebookEntriesAudioChat release];
currentPhonebookEntriesAudioChat = [entries retain];
}
}
}
-(NSMutableArray*)getCurrentPhonebookEntriesAudioChat
{
return currentPhonebookEntriesAudioChat;
}
-(void)setCurrentPhonebookEntriesTelepresence:(NSMutableArray *)entries
{
#synchronized(self) {
if (currentPhonebookEntriesTelepresence != entries)
{
[currentPhonebookEntriesTelepresence release];
currentPhonebookEntriesTelepresence = [entries retain];
}
}
}
-(NSMutableArray*)getCurrentPhonebookEntriesTelepresence
{
return currentPhonebookEntriesTelepresence;
}
-(void)setCurrentPhonebookEntriesVideoChat:(NSMutableArray *)entries
{
#synchronized(self) {
if (currentPhonebookEntriesVideoChat != entries)
{
[currentPhonebookEntriesVideoChat release];
currentPhonebookEntriesVideoChat = [entries retain];
}
}
}
-(NSMutableArray*)getCurrentPhonebookEntriesVideoChatLocal
{
return currentPhonebookEntriesVideoChat;
}
-(void)setCameleonVersion:(NSString *)cameleonversion
{
cameleonVersion = cameleonversion;
}
-(NSString*)getCameleonVersion
{
return cameleonVersion;
}
-(void)setIPaddress:(NSString *)ipaddress
{
ipAddress = ipaddress;
}
-(NSString*)getIPaddress
{
return ipAddress;
}
-(void)setPortNumber:(NSString *)portnumber
{
portNumber = portnumber;
}
-(NSString*)getPortNumber
{
return portNumber;
}
-(void)setSystemName:(NSString *)systemname
{
systemName = systemname;
}
-(NSString*)getSystemName
{
return systemName;
}
-(void)setIPID:(NSString *)ipid
{
iPID=ipid;
}
-(NSString*)getIpid
{
return iPID;
}
-(void)setSystemFeedBackName:(NSString *)systemfeedbackname
{
systemFeedBackName=systemfeedbackname;
}
-(NSString*)getSystemFeedBackName
{
return systemFeedBackName;
}
-(void)setDJoinConnectedFB:(NSString *)djoinconnectedfb
{
dJoinConnectedFB = djoinconnectedfb;
}
-(NSString*)getDJoinConnectedFB
{
return dJoinConnectedFB;
}
-(void)setDJoinLow:(NSString *)djoinlow
{
dJoinLow=djoinlow;
}
-(NSString*)getDJoinLow
{
return dJoinLow;
}
-(void)setDJoinHigh:(NSString *)djoinhigh
{
dJoinHigh = djoinhigh;
}
-(NSString*)getDJoinHigh
{
return dJoinHigh;
}
-(void)setAJoinLow:(NSString *)ajoinlow
{
aJoinLow = ajoinlow;
}
-(NSString*)getAJoinLow
{
return aJoinLow;
}
-(void)setAJoinHigh:(NSString *)ajoinhigh
{
aJoinHigh = ajoinhigh;
}
-(NSString*)getAJoinHigh
{
return aJoinHigh;
}
-(void)setSJoinLow:(NSString *)sjoinlow
{
sJoinLow = sjoinlow;
}
-(NSString*)getSJoinLow
{
return sJoinLow;
}
-(void)setSJoinHigh:(NSString *)sjoinhigh
{
sJoinHigh = sjoinhigh;
}
-(NSString*)getSJoinHigh
{
return sJoinHigh;
}
- (void)dealloc
{
[self.ipAddress release];
[self.iPID release];
[self.portNumber release];
[self.currentPhonebookEntriesVideoChat release];
[self.currentPhonebookEntriesTelepresence release];
[self.currentPhonebookEntriesAudioChat release];
[self.aJoinHigh release];
[self.aJoinLow release];
[self.cameleonVersion release];
[self.sJoinHigh release];
[self.sJoinLow release];
[self.dJoinHigh release];
[self.dJoinLow release];
[self.dJoinConnectedFB release];
[super dealloc];
}
#end
and then i use it in 3 classes total
in one i set values:
if i read values from the CCV (sharedobject) i get the correct values. but this is in the same class as they are set from
CCV = [CrestronControllerValues sharedManager];
CCV.currentPhonebookEntriesAudioChat = currentPhonebookEntriesAudioChat;
and another i read the values:
(these show/read as nil)
switch (viewOptions) {
case 1:
[self setTableArray:CCV.currentPhonebookEntriesVideoChat];
break;
case 2:
[self setTableArray:CCV.currentPhonebookEntriesVideoChat];
break;
case 3:
[self setTableArray:CCV.currentPhonebookEntriesTelepresence];
break;
case 4:
[self setTableArray:CCV.currentPhonebookEntriesAudioChat];
break;
default:
[self setTableArray:CCV.currentPhonebookEntriesVideoChat];
break;
}
but besides the class that i actually set the values in i do not get the filled array when i access it from another class
i have done NSLOG(#"%#", CCV) and from what i can see all three classes have the same pointer so the shared instance seems to be working
Here is a simplier singleton pattern, less code is more:
#implementation MySingleton
static MySingleton* _sharedMySingleton = nil;
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (!_sharedMySingleton)
_sharedSingleton = [[MySingleton alloc] init];
}
return _sharedMySingleton;
}
sharedMyManager has not been set at the time you are initializing the ivars.
In a init it is best practice to set the ivars directly, that is do not use setters such as created by #synthesize, the class is not completely established so calling methods on it is not a great idea.
A singleton is just a class like any other class with one exception, there is only one. Also all the extra methods to guarantee a singleton are really just noise that is best not present--but that is a matter of taste.
Consider:
sharedMyManager = [[super allocWithZone:NULL] init];
Rewrite it as:
id x = [super allocWithZone:NULL];
id y = [x init];
sharedMyManager = y;
When init is executed, the assignment to sharedMyManager hasn't been evaluated yet. Thus, sharedMyManager is nil and all your assignments are no-ops in your init method.
In your init method, you should always refer to your instance variables through self; either by directly assignment to them (which is a reference to self, really) or using the setter methods directly (i.e. self.foo = 442;).
(This is what #CocoaFu said, but clarified)
Looking at the code a little more closely, there are a ton of problems with it.
NSString properties should be copy, not retain.
you are leaking all of the currentPhonebookEntries* mutable arrays.
Getter methods should not have the prefix get*
there is no need to implement any of those getter/setter methods when using #synthesize (and you are actually creating two getter methods for each; one with and one without the get prefix).
the dealloc method should either directly release the instance variables or it should set the properties to nil; the [self.ivar release] is discouraged.
The code I showed above is merely illustrative. If your init still assigns through sharedMyManager, you didn't fix the problem.
so in the end all i can do is apologize. none of you had the code that you would have needed to see what was going on.
here is the array being saved (aboved was abridged (bad idea))
if ([phonebookEntriesAudioChat count] >=8) {
[CCV setCurrentPhonebookEntriesAudioChat:phonebookEntriesAudioChat];
[phonebookEntriesAudioChat removeAllObjects];
}
basically i was tring to add an item to the array from a socket return. getting one address up to 8 for each return/message. so i populated a temporary array (phonebookEntriesAudioChat) and added one to it for each message and once it got to 8 saved it to my singleton (CCV). but some how (and im still trying to figure this out) it would get to 8, be saved, temporary array cleared, then resaved the array (an empty one) to the singleton.
thanks for all the help and direction, i know i dont get points for my own answer if one of you wants some easy points just re answer with a simliar description as this and ill give u the check. otherwise im just going to vote up ur comments and mark this as the answer in a day or two.

NSNotification arrived with broken object

i'm posting notification in this manner:
...
IVSession *newSession = [[[IVSession alloc] initWithDictionary:propertyDict] autorelease];
NSDictionary *notifParams = [NSDictionary dictionaryWithObject:newSession forKey:#"session"];
NSNotification *newSessionNotif = [NSNotification notificationWithName:IVNewSessionNotificaiton object:self userInfo:notifParams];
...
IVSession interface:
#interface IVSession : IVMappableObject {
NSString *_ssid;
NSNumber *_uid;
}
#property (nonatomic,retain) NSString *sessionID;
#property (nonatomic,retain) NSNumber *userID;
and init method:
- (id)initWithDictionary:(NSDictionary*)dict
{
if ((self = [super init]))
{
NSDictionary *mapping = [self elementToPropertyMappings];
for (NSString *key in mapping)
[self setValue:[dict objectForKey:key] forKey:[mapping objectForKey:key]];
}
return self;
}
but at the method, called for this notification, i'm receiving broken newSession object - its properties ssid and uid are invalid summaries:
-(void)didOpenSession:(NSNotification *)newSession
{
if (receivedSession)
[receivedSession release];
receivedSession = [[newSession userInfo] objectForKey:#"session"];
}
where is my fault?
code looks ok to me... have you verified that the IVSession object contains what you expect it to, after assembling things, but prior to posting the notification?

Objective-c: NSMutableDictionary setObject not working

Not sure what I am doing wrong here. When I try to check the dictionary either by a specific key or allkeys I either get an error or null. (I know I'm using a string where I could be using a boolean for the conditional I just like having a check like that say true or false instead of YES and NO. Add that to my OCD list. :D ) activePlayer is set in an awakeFromNib method to 1, it can be switched using a popupbutton between P1 and P2.
- (IBAction)setPlayer:(id)sender {
haserror = #"false";
errmsg = [NSMutableString stringWithCapacity:0];
[errmsg retain];
[errmsg appendString: #"There was a problem setting your team up\n\n"];
thisTeamName = [txtTeamName stringValue];
thisTeamColor = [pdTeamColor itemTitleAtIndex:[pdTeamColor indexOfSelectedItem]];
//validate form
if ([thisTeamName isEqualToString:#""]) {
haserror = #"true";
[errmsg appendString: #"You must enter a team name\n\n"];
}
if ([thisTeamColor isEqualToString:#"Select A Color"]) {
haserror = #"true";
[errmsg appendString: #"You must select a team color\n\n"];
}
//check for errors
if (haserror == #"true") {
[self showAlert: errmsg];
} else {
//set up treasury
treasury = 1000;
//convert to string for display
[lblTreasury setStringValue: [NSString stringWithFormat:#"$%i", treasury] ];
//add items to dictionary
if (activePlayer == #"1") {
[p1TeamData setObject:thisTeamName forKey:#"teamName"];
[p1TeamData setObject:thisTeamColor forKey:#"teamColor"];
[p1TeamData setObject:[NSString stringWithFormat:#"%i", treasury] forKey:#"cash"];
} else {
[p2TeamData setObject:thisTeamName forKey:#"teamName"];
[p2TeamData setObject:thisTeamColor forKey:#"teamColor"];
[p2TeamData setObject:[NSString stringWithFormat:#"%i", treasury] forKey:#"cash"];
}
NSLog(#"%#", [p1TeamData allKeys]);
}
[errmsg release];
}
[Edit: here's the .h file]
#interface GameController :NSObject {
IBOutlet id btnSaveData;
IBOutlet id lblTreasury;
IBOutlet id pdPickPlayer;
IBOutlet id pdTeamColor;
IBOutlet id txtTeamName;
int activePlayer;
NSString* activePlayerName;
NSString* activePlayerTeamColor;
int treasury;
NSMutableDictionary* p1TeamData;
NSMutableDictionary* p2TeamData;
NSArray* players;
NSArray* teamColors;
NSArray* unittypes;
NSString* thisTeamName;
NSString* thisTeamColor;
NSMutableString* errmsg;
NSString* haserror;
}
-(void) awakeFromNib;
- (IBAction) getPlayer : (id)sender;
- (IBAction) setPlayer : (id)sender;
-(void) showAlert : (NSMutableString* ) m;
#end
Make sure you initialize the collections in the -initXXX method. If not, they will be assigned to nil.
-(id)initXXX:... {
if ((self = [super initYYY:...])) {
...
p1TeamData = [[NSMutableDictionary alloc] init];
p2TeamData = [[NSMutableDictionary alloc] init];
...
}
return self;
}
If all you want are "true" and "false", just define them yourself. It's not a reason to use string instead of BOOL. In fact, Foundation already defined TRUE and FALSE besides YES and NO.
Also, please use an integer for activePlayer.
You should always compare NSString with -isEqualToString:, not ==.
if ([haserror isEqualToString:#"true"])
...
if ([activePlayer isEqualToString:#"1"])
This should be the reason why p1TeamData is always nil, because activePlayer == #"1" is unreliable and there could be player-1 stuff assigned to p2TeamData.