How can I create array objects from UITextFields? - iphone

How can I create array objects from UITextFields? I also want an if statement for each object to check if the UITextField's text length is more than 1.
How can I do this using this core code?:
maincelltext = [[NSArray alloc] initWithObjects:#"UITextField 1 Content Here",#"UITextField 2 Content Here",#"UITextField 3 Content Here",#"UITextField 3 Content Here",nil];
Thanks!

Use NSMutableArray instead, and addObject: if(textField1.text.length > 1) then [yourMutableArray addObject:textField1.text]; and so on...
Something like this:
// in your interface
UITextField * textField1;
UITextField * textField2;
UITextField * textField3;
NSMutableArray * mainCellTextArray;
//implementation
mainCellTextArray = [[NSMutableArray alloc] init]; // release it later
if(textField1.text.length > 1)
{
[mainCellTextArray addObject:textField1.text];
}
if(textField2.text.length > 1)
{
[mainCellTextArray addObject:textField2.text];
}
if(textField3.text.length > 1)
{
[mainCellTextArray addObject:textField3.text];
}

Instead of creating an NSArray, I would use a IBOutletCollection and add all the UITextFields to it. You can do this easily through Interface Builder. To loop through and check that each has a text length of more than one is easily done whether you use NSArray or IBOutletCollection. Just use any of the many looping constructs (i.e. for, for-in) and check each item's text property's length.

Related

Display JSON as List in ViewController (Not in TableView)

I am producing a JSON string that I need to parse out and display onto the page. My JSON string outputs information about the contents of a CD like this:
[{"song_name":"Song 1","artist":"John","price":"$1"},
{"song_name":"Song 2","artist":"Anna","price":"$2"},
{"song_name":"Song 3","artist":"Ryan","price":"$3"}]
I would like to display the contents in my viewController in a list format displaying the song_name, artist, and price. I do not want to use a tableView to display this information, but would rather just have a list displayed. How might I go about doing this? I would assume that I need to use NSJSONSerialization, but have only used that for a tableView in the past. Thank you!
In addition to other answers, you can use only one label, just create NSMutableString (for dynamicly adding tracks info) with #"\n" between tracks info, pass it to label.text and set UILabel's property numberOfLines to 0
Follow these steps:
Parse the JSON and store the key-value pair(NSDictionary of CDs) in an NSArray (say infoArray)
Add a UIScrollview as a subview on your viewController's view.
Allocate UILabels dynamically, depending on infoArray count. Looking at your data I believe you can initialize labels with static frames i.e your y can remain static.
Add the text from the infoArray on this label.
Still, I would suggest use UITableView only. It is much simpler and a better approach
You make an array of dictionaries using NSJSONSerialization indeed, then you parse this array one by one and create a view of every dictionary. You're probably best of using a method for this:
-(UIView *) listView: (NSString *)songName andArtist:(NSString *)artist andPrice:(NSString *)price andIndex:(int)viewIndex {
//create your view here and do anything you want
UIView *subView = [[UIView alloc] init] autoRelease];
subView.frame = CGRectMake(0, viewIndex * 70, self.view.frame.width, 70);
//add labels and other stuff
// return the view
return subView;
}
The you add it to the current view by setting different Y values so they appear underneath each other by using the viewIndex of the former method... So if you have an array it goes something like this:
for (int i = 0; i < [array count]; i++) {
NSDictionary *dict = [array objectAtIndex:i];
NSString *songName = [dict valueForKey:#"song_name"];
NSString *artist = [dict valueForKey:#"artist"];
NSString *price = [dict valueForKey:#"price"];
UIView *tempView = [self listView:songName andArtist:artist andPrice:price andIndex:i];
[self.view addSubView:tempView];
}
You have to add it all to a scrollview otherwise you will run into the problem of to many rows on the page. Google for UIScrollView if you don't know how.
But I would recommend against this approach.. Tableviews are there with a reason. They are made for this stuff. Because the also provide for scrolling, drawing and refreshing. If you can, use them!

Trying to Concatenate Object names in Objective-C

I know I can concatenate a variable name using stringwithformat, but is it possible to concatenate an object name? I'm not having any luck working around this one.
image+1.hidden = YES; for example.
If I wanted to loop through that, say 10 times, how would I create the 'image+1' part?
Thanks for any help.
I don't think that it is possible to concatenate object names in objective c, but you could create an array of images, and then reference each image like
image[0].hidden = YES;
That would fit the for loop. You could also add the images (I assume that they are UIImages) to an NSArray, then loop through like so:
NSArray* arrayOfImages;
for(UIImage* image in arrayOfImages)
{
image.hidden = YES;
}
Add the objects to an NSArray or NSMutableArray. Then loop through the array to set each object's properties.
For the purposes of discussion mainly, you can use key-value coding to set a property by its name. So, supposing you had instance, an instance of a class that provides the properties image1, image2 and image3 then you could perform:
for(int x = 1; x < 4; x++)
{
// produce the name of the property as an NSString
NSString *propertyName = [NSString stringWithFormat:#"image%d", x];
// use key-value coding to set the property
[instance setValue:someValue forKey:propertyName];
}
For the full list of accessor methods that compliant classes export, see the NSKeyValueCoding Protocol Reference. NSObject implements NSKeyValueCoding, and all properties declared as #property and implemented as #synthesize are compliant, as are any other properties with suitable accessors.
As already noted in the other answers, when what you want is an ordered list of objects so that you can do something with each in turn, either a C-style array or an NSArray is the correct way to proceed, with an NSArray being preferred for style reasons.
NSArray *array = [[NSArray alloc] initWithObjects:image1, image2, image3, image4, image5, image6, image7, image8, image9, image10, nil]; // or use NSMutableArray
for (int x = 0; x < 10; x++) {
((UIImage*)[array objectAtIndex:x]).hidden = YES;
}

Passing Array From Controller to View

I have:
UIView
UIViewController
In the UIViewController I need to be able to insert items into a fixed array of 6 integers. Then, I need to pass this array to the view in order for it to analyse the array and update the screen appropriately. How do I go about doing this? I've tried using standard C arrays but doesn't seem to work?
You can't use C arrays as arguments to methods, nor can you pass them to something. You have two options:
Use an NSArray of six NSNumbers, each containing an int.
Use a pointer to the C array.
Which one you choose is up to you. Option 1 is more iPhone-alike. Option 2 is less memory-consuming.
Because objective c doesn't allow C arrays to be passed to objective c methods unless they are sent as pointers, Here is one method:
// MyViewController.m
#define BOX_INT(ARG_1) [NSNumber numberWithInt:ARG_1];
....
-(void) somethingHappened:(id) sender
{
// initialize the array:
NSArray *array = [NSArray arrayWithObjects:BOX_INT(ints[0]), BOX_INT(ints[1]), BOX_INT(ints[2]), BOX_INT(ints[3]), BOX_INT(ints[4]), BOX_INT(ints[5]), nil];
[myView passArray:array];
}
// MyView.m
#define UNBOX_INT(ARG_1) [ARG_1 intValue];
....
-(void) passArray:(NSArray *) array
{
int intArray[6];
for (int i = 0; i < 6; i++)
{
intArray[i] = UNBOX_INT([array objectAtIndex:i]);
}
...
}
Or, you can just pass a pointer (not recommended)
// MyController.m
-(void) somethingHappened:(id) sender
{
[myView passArray:ints];
}
-(void) passArray:(int *) array
{
// think of array as an integer array, with a length of 6.
}
There' has always been a discussion for how to share objects between two classes .
So broadly speaking there are three methods:-
Singleton Objects
Global Variables
Appdelegate variables
However if u really want to pass an array from ViewController to View , I would recommend going with 3rd method i.e. AppDelegate Variables. And yes that's always pointed that this is quick but Dirty method.
So what you can do is declare and Array in Appdelegate.
Now to insert items into that array in ur viewcontroller
UrAppDelegate* delegate = (UrAppDelegate*)[[UIApplication sharedApplication]delegate];
[delegate.urArrayName addObject:#"someObject"];
And then when u want to use that in ur view.. just go ahead and use the same method above.

replaceObjectAtIndex array problems

Been searching for the answer to this for a while now and I think due to the nature of my array set up, I may be searching for the wrong answer!
I have a class which handles adding items to my array:
// Item.h
#interface Item : NSObject {
NSString *name;
NSNumber *seconds;
}
#property(nonatomic,copy) NSString *name;
#property(nonatomic,copy) NSNumber *seconds;
- (id)initWithName:(NSString *)n seconds:(NSNumber *)sec;
#end
and...
//item.m
#implementation Item
#synthesize name, seconds;
- (id)initWithName:(NSString *)n seconds:(NSNumber *)sec {
self.name = n;
self.seconds = sec;
return self;
}
#end
So to add an item, I use
Item *item1 = [[Item alloc] initWithName:#"runnerA" seconds:[NSNumber numberWithInt:780]];
I have some code which allows a user to edit a textfield (runner name) and the time which is a UIdatepicker set to hours and minutes. In the save method, that's working fine. It's the UPDATE that I cannot get to work. I've tried alsorts! Here's the code at the moment...
mainAppDelegate *appDelegate = (mainAppDelegate *)[[UIApplication sharedApplication] delegate];
Item *item = [[Item alloc] initWithName:inputName.text seconds:[NSNumber numberWithInt:secs]];
[appDelegate.arrItems replaceObjectAtIndex:rowBeingEdited withObject:item];
The above is simply adding a new item to the array (which is what I don't want). I'm not sure how to replace values. At the function, I have the row I need to update (rowBeingEdited) and the fields inputName.text and secs are both OK. (NSLog out confirms this).
How do I use the replaceObjectAtIndex to actually replace it with the values?! It's driving me mad now!!
Since you are simply trying to edit a particular row, why not use those property accessors that you already have set up in Item? It would look something like this:
Item *item = (Item *)[appDelegate.arrItems objectAtIndex:rowBeingEdited];
[item setName:inputName.text];
[item setSeconds:[NSNumber numberWithInt:secs]];
An a side note, are you using garbage collection, or do you manually release the Item objects that you create when adding items to the array? If you are doing it manually, it should look like this:
Item *item1 = [[Item alloc] initWithName:#"runnerA"
seconds:[NSNumber numberWithInt:780]];
[appDelegate.arrItems addObject:item1];
[item1 release];
This follows the rule of thumb: if you alloc, copy or retain anything, you must also release it. Note that this works because the array will retain the item when it is added.
Are you using NSArray or NSMutableArray?
Assuming you are using NSMutableArray, how did you initialize and populate the array in the first place?
For example, it's not enough to use -initWithCapacity: or +arrayWithCapacity: which only sets aside space. You have to use -addObject: for the first round of population, before you can use -replaceObjectAtIndex:withObject::
Note that NSArray objects are not like C arrays. That is, even though you specify a size when you create an array, the specified size is regarded as a “hint”; the actual size of the array is still 0. This means that you cannot insert an object at an index greater than the current count of an array. For example, if an array contains two objects, its size is 2, so you can add objects at indices 0, 1, or 2. Index 3 is illegal and out of bounds; if you try to add an object at index 3 (when the size of the array is 2), NSMutableArray raises an exception.

Retrieve NSNumber From Array

I am relatively new to Objective C and need some array help.
I have a plist which contains a Dictionary and an NSNumber Array, with more arrays to
be added later on.
NSMutableDictionary *mainArray = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
NSArray *scoresArray = [mainArray objectForKey:#"scores"];
I need to retrieve all the values from the array and connect them to 10 UILabels which
I've set up in interface builder. I've done the following to cast the NSNumber to a String.
NSNumber *numberOne = [scoresArray objectAtIndex:0];
NSUInteger intOne = [numberOne intValue];
NSString *stringOne = [NSString stringWithFormat:#"%d",intOne];
scoreLabel1.text = stringOne;
This seems a very long winded approach, I'd have to repeat the 4 lines above ten times to retrieve all the array values. Could I use a for loop to iterate through the array with all of the values converted to Strings at the output?
Any info would be greatly appreciated.
// create NSMutableArray* of score UILabel items, called "scoreLabels"
NSMutableArray *scoreLabels = [NSMutableArray arrayWithCapacity:10];
[scoreLabels addObject:scoreLabel1];
[scoreLabels addObject:scoreLabel2];
// ...
NSUInteger _index = 0;
for (NSNumber *_number in scoresArray) {
UILabel *_label = [scoreLabels objectAtIndex:_index];
_label.text = [NSString stringWithFormat:#"%d", [_number intValue]];
_index++;
}
EDIT
I'm not sure why you'd want to comment out _index++. I haven't tested this code, so maybe I'm missing something somewhere. But I don't see anything wrong with _index++ — that's a pretty standard way to increment a counter.
As an alternative to creating the scoreLabels array, you could indeed retrieve the tag property of the subviews of the view controller (in this case, UILabel instances that you add a tag value to in Interface Builder).
Assuming that the tag value is predictable — e.g., each UILabel from scoreLabel1 through scoreLabel10 is labeled with a tag equal to the values of _index that we use in the for loop (0 through 9) — then you could reference the UILabel directly:
// no need to create the NSMutableArray* scoreLabels here
NSUInteger _index = 0;
for (NSNumber *_number in scoresArray) {
UILabel *_label = (UILabel *)[self.view viewWithTag:_index];
_label.text = [NSString stringWithFormat:#"%d", [_number intValue]];
_index++;
}
The key to making that work is that the tag value has to be unique for the UILabel and must be something you can reference with -viewWithTag:.
The code above very simply assumes that the tag values are the same as the _index values, but that isn't required. (It also assumes the UILabel instances are subviews of the view controller's view property, which will depend on how you set up your interface in Interface Builder.)
Some people write functions that add 1000 or some other integer that allows you group types of subviews together — UILabel instances get 1000, 1001, and so on, and UIButton instances would get 2000, 2001, etc.
try using stringValue...
scoreLabel1.text = [(NSNumber *)[scoresArray objectAtIndex:0] stringValue];