This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm new to iPhone development,I want to initialize strings in an array like the given format
-(IBAction)btnSubmit:(UIButton *)sender
{
NSString *phone = phoneNumber.text;
NSLog(#"Phone :%#",phone);
NSString *TxtUserName = userName.text;
NSString *TxtEmailId = emailId.text;
NSArray *details = [NSArray arrayWithObjects:TxtUserName,TxtEmailId,phone,nil];
}
I'm getting details :(
"xxxxxxx",
"xxxxx#gmail.com",
7675
)
I want to get details :("Name=xxxx","Email=xxxx#gmail.com","Phone=8786")
Any ideas? Thanks in advance.
initialize array like
NSMutableArray *dummyArr = [ [ NSMutableArray alloc] init];
[dummyArr addObject #"Adam"];
[dummyArr addObject #"John"];
Either NSDictionary is what you need, however if you want in the format you have specified in the question:
NSString *phone = NSString stringWithFormat:#"Phone=%#",phoneNumber.text];
NSLog(#"Phone :%#",phone);
NSString *TxtUserName = [NSString stringWithFormat:#"Name=%#",userName.text];
NSString *TxtEmailId = [NSString stringWithFormat:#"Email=%#",emailId.text];
NSArray *details = [NSArray arrayWithObjects:TxtUserName,TxtEmailId,phone,nil];
The other answers mentioned here deal with the part of using NSDictionary/NSMutableDictionary.
Use NSDictionary or NSMutableDictionary: can handle key value pair
Array can store only objects,what you need is key-value pair mechanism
you can do like below...
dictMut=[[NSMutableDictionary alloc]init];
[dictMut setObject:#"xxxx" forKey:#"Name"];
[dictMut setObject:#"xxxx#gmail.com" forKey:#"email"];
[dictMut setObject:#"8786" forKey:#"phone"];
NSMutableArray *temp=[NSMutableArray alloc]init];
[temp addObject:dictMut];
Happy Coding!!!
What you could do is:
NSDictionary *dictionary = #{#"name": userName.text, #"email":emailId.text};
Or use NSMutableDictionary if you want to change the objects.
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"John" forKey:#"Firstname"];
[dict setObject:#"Doe" forKey:#"Lastname"];
[dict setObject:#"info at objectgraph.com" forKey:#"Email"];
NSLog(#"%#", dict);
NSArray *keys = [dict allKeys];
// values in foreach loop
for (NSString *key in keys) {
NSLog(#"%# is %#",key, [dict objectForKey:key]);
}
NSDictionary *dict = [[NSDictionary alloc] init];
[dict setValue:TxtUserName forKey:#"Name"];
[dict setValue:TxtEmailId forKey:#"Email"];
to get it back:
[dict valueForKey:#"Name"];
You can use NSDictionary for this type of work. You can do it using this two method.
NSDictionary * = [NSDictionary dictionaryWithObjectsAndKeys:userName.text,#"Name",emailId.text,#"Email",phoneNumber.text,#"phone" nil];
Or you can do it like this.
NSMutableDictionary *eventData = [NSDictionary dictionaryWithObjectsAndKeys:userName.text,#"Name", nil];
[eventData setObject:emailId.text forKey:#"Email"];
[eventData setObject:phoneNumber.text forKey:#"phone"];
Try:
NSMutableDictionary* dict = [NSMutableDictionary new];
[dict setObject:#"Bob Jones" forKey:#"name"];
[dict setObject:#31337 forKey:#"number"];
[dict setObject:#"Turkey" forKey:#"location"];
OR, shorthand:
NSDictionary dict = #{#"name": #"Bob Jones", #"number": #31337, #"location": #"Turkey"};
The #31337 is objective-c shorthand for [NSNumber numberWithInt:31337] and is needed because NSDictionary / NSMutableDictionary can only store NSObject-derived classes.
In the first example, you're defining a blank NSMutableDictionary and then adding stuff to it. In the second, you're creating a constant, immutable, unchangeable dictionary with some keys and values in it. Example 1 and example 2 have the same data in it, but you can add / delete stuff from the first example.
Also, NSMutableDictionary is a subclass of NSDictionary, which means you can pass it to functions that accept NSDictionary. You cannot cast the other way.
You can use an NSDictionary which will allow you to store the individual bits of data you require, but you might also want to follow the MVC-design pattern which is very important in the Cocoa and Cocoa Touch frameworks.
In the MVC design pattern the data you are attempting to represent is the Model, so if you are doing anything non-trivial with the data you will want to create one or more objects representing the data, which can then be passed around your app and used appropriately.
It would be declared something like:
MyModel.h:
#interface MyModel : NSObject
#property (strong, readwrite) NSString *username;
#property (strong, readwrite) NSString *phoneNumber;
#property (strong, readwrite) NSString *emailAddress;
#end
In the implementation file (MyModel.m) you don't even have to use #synthesize these days as Apple considers that to be too much typing. Instead the modern clang compiler will auto-generate the backing instance variables on your behalf. Just remember to reference these properties using myobject.username or self.username rather than simply _username.
You can then consider adding methods that allow the data to be manipulated. In this way your allow your model to change over time without having to re-code significant parts of your app, which would otherwise rely on an NSDictionary with a fixed key name, which will simplify the maintenance of your app.
While using dictionary is a very good option creating a model class for storing user info would be more useful. You can create methods which would work on the data for more reusability and keeping things simple.
#interface User : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *emailID;
#property (nonatomic, copy) NSString *phoneNumber;
- (id)initWithName:(NSString *)name
emailID:(NSString *)emailID
andPhoneNumber:(NSString *)phoneNumber;
Create user instance and set the values
-(IBAction)btnSubmit:(UIButton *)sender
{
User *user = [User new];
user.name = userName.text;
user.emailID = emailId.text;
user.phoneNumber = phoneNumber.text;
//Use this instance for your work
}
First set your data to NSMutableDictionary.........
Dic=[[NSMutableDictionary alloc]init];
[Dic setObject:#"xxxx" forKey:#"Name"];
[Dic setObject:#"xxxx#gmail.com" forKey:#"email"];
[Dic setObject:#"8786" forKey:#"phone"];
And then get data from NSMutableDictionary....
Related
I am trying to store all of the items scrolled past in my UITableView in an NSMutableArray. In my cellForRowAtIndexPath method I include the code below. All of the objects (Id, currentTime, et...) are NSStrings.
I am trying to compile all of them into a single array, but I don't think I am doing this correctly. I think I might be overwriting the dictionary in every single cellForRowAtIndexPath.
Any help would be great. At the end, I just want a single array that allows me to look up various aspects of the "rows/cells" that were scrolled past...
In my .m file:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:Id forKey:#"key1"];
[dict setObject:currentTime forKey:#"key2"];
[dict setObject:textForMyLabel forKey:#"key3"];
[dict setObject:placeLatitude forKey:#"key4"];
[dict setObject:placeLongitude forKey:#"key5"];
[scrolledPast addObject:dict];
NSLog(#"array: %#", dict);
In my .h file:
#interface viewController {
NSMutableArray *scrolledPast;
}
#property (nonatomic, retain) NSMutableArray *scrolledPast;
You need to initialize your scrolledPast.
Do this in your viewDidLoad:
- (void) viewDidLoad {
// .....
scrolledPast = [NSMutableArray array];
}
How can I add object at specified index?
in my problem
NSMutableArray *substring
contains index and object alternatively
and I need to add it to the another array str according to index I getting from this array.
NSMutableArray *str=[NSMutableArray new];
if ([substrings containsObject:#"Category-Sequence:"])
{
NSString *index=[substrings objectAtIndex:5];
//[substrings objectAtIndex:5]
gives me integer position at which I need to add object in `str` array,
gives 5,4,8,2,7,1 etc
NSString *object=[substrings objectAtIndex:1];
//[substrings objectAtIndex:1] gives object,gives NSString type of object
[str insertObject:object atIndex:(index.intValue)];
}
please suggest some way to achieve it.
Thanks in advance!
Allocate the array first & then try to add objects in it.
NSMutableArray *str = [[NSMutableArray alloc]init];
if ([substrings containsObject:#"Category-Sequence:"])
{
NSString *index=[substrings objectAtIndex:5];
NSString *object=[substrings objectAtIndex:1];
[str insertObject:object atIndex:(index.intValue)];
}
Allocate the NSMutableArray before inserting objects into it:
NSMutableArray *strMutableArray = [[NSMutableArray alloc] init];
(You’ll also need to release it when you’re done if you’re not using ARC.)
Or you could also use a temporary object, if you don’t need to keep strMutableArray:
NSMutableArray *strMutableArray = [NSMutableArray array];
Then you can insert objects into the NSMutableArray.
Be careful with using indexes of and in different arrays, however. There might be a better way to do what you want.
So I have an array of NSDictionaries, each NSDictionary has a bunch of key/value pairs pertaining to aspects of a photo (from Flickr).
I'm making an app that has a UITableViewController whose cells should be each of the different categories of the photos. So in pseudocode, I'm trying to construct a new NSDictionary (with keys being categories of photos, values being the NSDictionaries of the photos that contains that key). I'm iterating through each NSDictionary in the initial array, getting the category tags, and saying, if my new NSDict doesn't contain this key, make a new key to an empty array. Then add the current NSDict to that array. I'm getting consistent errors, not sure why.
Here's the diluted code.
photoList = [FlickrFetcher photosWithTags:[NSArray arrayWithObjects: #"CS193p_SPoT", nil]];
NSLog(#"%#", photoList);
categories = [[NSDictionary alloc] init];
NSArray *temp = [[NSArray alloc] init];
for (id obj in photoList) {
temp = [[obj objectForKey:#"tags"] componentsSeparatedByString:#" "];
for (id string in temp) {
if (![categories objectForKey:string]) {
NSMutableArray *arr = [[NSMutableArray alloc] init];
[categories setObject:arr forKey:string];
//[arr release];
}
NSMutableArray *photos = [categories objectForKey:string];
[photos addObject:obj];
[categories setObject:photos forKey:string];
}
}
Thanks!
NSDictionary doesn't have a method setObject:forKey:. You need an NSMutableDictionary.
self.categories = [NSMutableDictionary dictionary];
Other than that, please do use Joost's excellent rewrite of your code.
SIGABRT, just so you know, most likely means that an assertion somewhere failed. In this case, it may be an assertion all the way down in CoreFoundation*; CF checks for mutability when you try to access a dictionary like that and causes an interrupt if the object isn't mutable.
*I have just learned about the CF source's availability recently and have been looking through it, so this may be just "new thing" bias and incorrect.
I don't notice any errors (syntax-errors, that is) in your code, however here is an updated piece of code which has been implemented a bit cleaner (and without memory leaks)
self.photoList = [FlickrFetcher photosWithTags:[NSArray arrayWithObjects: #"CS193p_SPoT", nil]];
NSLog(#"%#", photoList);
self.categories = [NSDictionary dictionary];
for (NSDictionary *obj in photoList) {
NSArray *temp = [[obj objectForKey:#"tags"] componentsSeparatedByString:#" "];
for (NSString *string in temp) {
NSMutableArray *photos = [categories objectForKey:string];
if (!photos) {
photos = [NSMutableArray array];
[categories setObject:photos forKey:string];
}
[photos addObject:obj];
}
}
If it's not working please tell us the exact warning, and were it is caused.
I have a list of shops in a ListController file.
I've setted up a sqlite db, in which i've stored 60 shops.
On the top of the list i have a search bar.
I've made a class called DataController, that is responsible to load and store db datas.
#interface DataController : NSObject {
sqlite3 *database;
NSArray *shops;
NSDictionary* dictionaryOfShops;
}
#property (nonatomic, retain) NSDictionary *dictionaryOfShops;
#property (nonatomic, retain) NSArray* shops;
-(void)initializeShops;
initializeShops method loads data from the db, and stores results into the 2 props in this way:
-(void)initializeShops{
[dictionaryOfShops release];
[shops release];
NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];
if (sqlite3_open(....))
NSString *query = ....
if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW) {
int rId = sqlite3_column_int(statement, 0);
char *rName = (char *)sqlite3_column_text(statement, 1);
Shop* s = [[Shop alloc] init];
s.ID = rId;
if(sName != nil) s.Name = [NSString stringWithUTF8String:rName];
NSString *shopID = [[NSString alloc] initWithFormat:#"%d",s.ID];
[dictionary setObject:s forKey:shopID];
[shopID release];
[s release];
}
sqlite3_finalize(statement);
}
[query release];
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
dictionary = nil;
[dictionary release];
//Sorting
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES];
NSArray *sortedList =[self.shops sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
self.shops = sortedList;
[sort release];
}
The problem is that when user enters some text into the search
bar, I change the value of the query (adding LIKE....) and then call the initializeShops method again. This second time makes
so many leaks, (related to the Shop class properties) and
leaks also a NSDictionary and a NSArray.
Before posting this to you I've tried different solutions, but
at least this doesn't leaks anything the first time I call
initilizeShops.
I accept any suggestion, since I'm really stuck
on it.
MORE:
The really strange thing is memory management of my var dictionary and the 2 props shops and dictionaryOfShops. With this code
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//add data to dictionary
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops = [[NSArray alloc] initWithArray:[dictionary allValues]];
[dictionary release]
Considering that dictionaryOfShops and shops are two properties (nonatomic,retain) synthesized, how can I change value to them without leaks?
The very first time I pass through this method nothing gets leaked, from the second time it starts to leak so many objects (the contents of the collections).
The first question is Why not just use Core Data? It is very likely going to be faster, will require less code, and will be significantly easier to maintain over time. To be blunt; SQLite is deceptively hard. Easy to get started, exceptionally difficult to get right.
In any case, the memory management of dictionary is wrong. It only isn't crashing because you swapped the order of the nil assignment and release as kennyTM suggested. I would suggest not creating an autoreleased dictionary.
Otherwise, the code as written seems pretty leakless at first glance. So:
Can you provide some more code?
Anything interesting memory wise
going on elsewhere?
Are you using threading at all (or
NSOperationQueue)?
Have you run under the Leaks
instrument and retrieved the
backtraces of allocation of the
specific objects being leaked?
dictionary = nil;
[dictionary release];
Please swap these 2 statements. In this form it means [nil release] which is a no-op.
Ok, I've found the error.
In my class Shop, i realize i didn't implement the method
-(void)dealloc
So when I release the old dictionary (to prepare for a new assignment), all the fields inside of it didn't get released.
Is it acceptable to have a NSMutableArray within an NSDictionary? Or does the NSDictionary also have to be mutable?
The NSMutableArray will have values added to it at runtime, the NSDictionary will always have the same 2 NSMutableArrays.
Thanks,
Dan
Yes, it's perfectly acceptable. Keep in mind, the contents of the array are the pointers to your NSMutableArrays--those are what can't change in the immutable dictionary structure. What the pointers point to can change all you want. To wit:
NSMutableArray *arr = [[NSMutableArray alloc] init];
NSDictionary *dict = [NSDictionary dictionaryWithObject:arr forKey:#"test"];
[arr addObject:#"Hello"];
NSString *str = [[dict objectForKey:#"test"] objectAtIndex:0];
NSLog("%#", str);
It's quite acceptable. But, it's precisely the sort of setup that suggests you should seriously consider replacing the dictionary with an NSObject subclass that sports two properties for accessing the arrays.