I am struggling with a dictionary in which I want to create a new dictionary from a series of keys (P, SP, and RP).
I have attempted to create a new NSMutableDictionary that combines individual Dictionaries that have have all the values for the P, SP, and RP keys respectively, but have gotten the error "No class method for selector "addEntriesFromDictionary" "
Here is my code:
NSMutableDictionary *newDict = [NSMutableDictionary addEntriesFromDictionary:self.allSPPositions];
and
#interface className ()
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
#end
#implementation className
- (void)viewDidLoad {
Any help or insight would be appreciated! Thanks!
The compiler is telling you exactly what's wrong. You're trying to add items from a dictionary to the NSMutableDictionary class. You need to send the ad items from dictionary message to an instance of NSMutableDictionary.
This line:
NSMutableDictionary *newDict =
[NSMutableDictionary addEntriesFromDictionary:self.allSPPositions];
Should read
NSMutableDictionary *newDict =
[someDictionary addEntriesFromDictionary: self.allSPPositions];
(Where someDictionary is the dictionary to which you want to add items.)
or even
NSUInteger count = [self.allSPPositions count];
NSMutableDictionary *newDict =
[NSMutableDictionary dictonaryWithCapacity: count];
[newDict addEntriesFromDictionary: self.allSPPositions];
(Since your code appears to be trying to create a new, mutable dictionary and add the contents of self.allSPPositions.)
If your goal is to get a mutable copy of self.allSPPositions, there is a cleaner way to do that:
NSMutableDictionary *mutablePositions = [self.allSPPositions mutableCopy];
Uhh, here's an example that will compile and use the method in question, you should probably NOT call that method in your Interface since it's part of Apple's framework and is already predefined, unless you have a special reason for doing so:
NSMutableDictionary *dict =[[NSMutableDictionary alloc] init];
[dict setValue:#"Seattle" forKey:#"name"];
[dict setObject:[NSNumber numberWithInt:3] forKey:#"age"];
[dict setObject:[NSDate date] forKey:#"date"];
dict[#"city"]=#"Seattle";
[dict addEntriesFromDictionary:[NSMutableDictionary dictionaryWithObjectsAndKeys: #"Washington",#"location", nil]];
This is merely meant to get you started, but it shows you how to do this so that it works for you in your circumstances
Related
I just learned how to make use of KVO, but only the basics. What I need to achieve is something like this:
I have a delegate call that passes a Speaker object.
- (void)onSpeakerFound:(Speaker *)speaker
Once I receive this Speaker in the UI part, from there I will assign observers for this object.
But, this is just for one speaker. What if I have multiple speakers to keep track of. I need to assign observers separately for those speakers and then at the same time I wish to keep their references for further updates to the values.
Each speaker could be updated from time to time. So when I notice that there is a change that happened on a speaker, I wish to access the reference to that speaker and update the values just like how NSMutableDictionary works.
NSMutableDictionary makes a copy of an object set to it so it will be a difference object if I get it again from the dictionary.
So, is there a class that allows me to keep track of an object by just keeping a reference only to that object without making a copy of it?
EDIT: A Test Made To Verify That When An Instantiated Object is Set in an NSMutableDictionary, The Instantiated Object is not referenced with the one set inside NSMutableDictionary.
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *obj = #"initial value";
NSString *key = #"key";
[dict setObject:obj forKey:key];
NSLog(#"Object is now %#", [dict objectForKey:key]);
obj = #"changed value";
NSLog(#"Object is now %#", [dict objectForKey:key]);
}
Log:
2016-07-26 21:04:58.759 AutoLayoutTest[49723:2144268] Object is now initial value
2016-07-26 21:04:58.761 AutoLayoutTest[49723:2144268] Object is now initial value
NSMutableDictionary makes a copy of an object set to it...
That is not correct; it will add a reference to the object. It will be the same object referenced inside and outside the Objective-C collection.
So, is there a class that allows me to keep track of an object...?
Probably NSMutableSet if you just want a list of the objects. That will take care that you have a unique reference to each object, however you need to implement the methods hash and isEqual on those objects so they behave correctly. Otherwise NSMutableDictionary if you want fast look-up by key.
-try this one
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSString *obj = #"initial value";
NSString *key = #"key";
[dict setObject:obj forKey:key];
NSLog(#"Object is now %#", [dict objectForKey:key]);
obj = #"changed value";
[dict setObject:obj forKey:Key];
NSLog(#"Object is now %#", [dict objectForKey:key]);
}
I have the following code:
for (NSMutableDictionary *aDict in array)
{
// do stuff
[aDict setObject:myTitle forKey:#"title"];
}
My question is, if the array is filled with NSDictionary objects, will this for loop code as written automatically convert them into NSMutableDictionary objects?
Or do I need to do something more specific here to ensure that I don't get an unrecognized selector sent to instance error on setObject:forKey: in the loop?
Currently that will give you the error you mentioned. Whilst the loop is setup with mutable dictionaries, the underlying object is still immutable. You'd need to create a new dictionary out of it. Try this
NSMutableArray *newArray = [NSMutableArray array];
for (NSDictionary *aDict in array)
{
NSMutableDictionary *mutable = [aDict mutableCopy];
// do stuff
[mutable setObject:myTitle forKey:#"title"];
[newArray addObject:mutable];
}
No it will not automatically convert them. You have to do that yourself. You'll definitely get the unrecognized selector sent to instance exception.
While trying to set a single key/value pair in NSMutableDictionary of NSMutableArray like:
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
self.items is NSMutableArray and it have a list of NSMutableDictionaries
Instead of setting to that single object, it set it to all dictionaries in the list.
I have used this method before. But I don't know what is happening in this case.
I know NSArray have setValue:#"value" forKey:#"key method, but in this case I am using NSMutableArray
Here is a bit more block of code to help clarify my situation:
-(void)setItem:(id)sender
{
for (CellView *cell in self.CollectionView.visibleCells)
{
NSIndexPath *indexPath = [self.CollectionView indexPathForCell:cell];
int i = (indexPath.section * (mainItems.count)/3+ indexPath.row);
if (((UIButton *)sender).tag == i)
{
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
}
}
}
Call setObject:forKey:, not setValue:forKey:. There is a difference.
Note that NSMutableArray extends NSArray so NSMutableArray has all of the methods of NSArray.
I also recommend you split your line up as well as use modern syntax:
NSMutableDictionary *dict = self.items[i];
dict[#"key"] = #"value";
NSMutableArray is a subclass of NSArray so all the NSArray methods are still there in NSMutatbleArray. You could try pulling it out and putting it back in to figure things out then reassemble your code after...
NSMutableDictionary *d = [self.items objectAtIndex:i];
[d setValue:#"value" forKey:#"key"];
[self.items setObject: d atIndexedSubscript: i];
This is a little more explicit which will allow you to debug it easier (not getting unexpected nils back, etc.).
Ok I got the issue.
I am working on a large pre-existing code. And I come to notice that The MutableDictionary was defined globally and the same object was being added to the MutableArray. So basically all the pointers in the MUtableArray where pointing to a single object.
How can i retrieve the key value from the below NSMutableArray array. The below code crashes on isEqualToString. However i can see the value of nsRet in the variable view window as #\x18\xaa\x01\xc8\a before running that statement.
NSMutableArray* nsMyList = [[NSMutableArray alloc] init];
[nsMyList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"valueOfKey", #"Key",
nil]];
NSString *nsRet = [nsMyList valueForKey:#"Key"];
if ([nsRet isEqualToString:#"deviceClass"])
{
NSLog(#"Key value:%#", nsRet);
}
Can anyone here please help me get the correct value for the key?
Thanks.
This is because you need objectForKey:, not valueForKey:. The valueForKey: method is for key-value programming. Moreover, the call should be on the [nsMyList objectAtIndex:0], like this:
NSString *nsRet = [[nsMyList objectAtIndex:0] objectForKey:#"Key"]
You've stored the NSDictionary in an array. The correct access based on your code would be:
NSDictionary *dict = [nsMyList objectAtIndex:0];
nsret = [dict valueForKey:#"Key"];
It looks like you are trying to get the valueForKey: on an NSMutableArray rather than on the dictionary.
What you want is:
[[nsMyList objectAtIndex:0] valueForKey:#"Key"];
I am a bit lost.
In order to access the dictionary you just create you need to obtain the first element in the NSMutableArray and then the dictionary.
It will be something like this:
NSString *nsRet = [nsMyList[0] objectForKey:#"Key"]
I think it can solve it.
I have a class that parses through an XML file in iOS.
You can get the data of an element in the form of an TBXMLElement*.
I want to iterate through the XML and make deep copies of the TBXMLElements and store them in an NSMutableDictionary class variable.
How can I:
myClassDict addObject:(TBXMLElement*)element?
You can put the pointers in an NSValue. What key are you going to use?
// Save the TBXMLElement*
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:[NSValue valueWithPointer:element] forKey:#"whatKey"];
…
// Get the TBXMLElement*
TBXMLElement *el = (TBXMLElement *)[[dict valueForKey:#"whatKey"] pointerValue];
Like said in the comments, you will have to wrap TBXMLElement* in a subclass of NSObject. Probably something like:
#interface MyXMLElement {
TBXMLElement* _xmlElement;
}
-(void)setXMElement:(TBXMLelement*)element;
#end
You can then populate the element:
MyXMLElement *elmt = [[MyXMLElement alloc] init];
[emlt setXMLElement:pointerToTBXMLElement];
[someArray addObject:elmt];