Passing Array From Controller to View - iphone

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.

Related

NSInteger value not valid when passing in a variable, for custom table view class delegate method

I'm testing a custom table view style class:
HorizontalTable
It produces a horizontal table view.
One of the delegate methods equivalent to tableView:numberOfRowsInSection: is:
- (NSInteger)numberOfColumnsForTableView:(HorizontalTableView *)tableView.
If I give this a number (ex: return 10;) it is happy and it give me the number "cells" that I want. But if I feed it a value of someArray.count or an int or NSInteger variable, the table view just comes out blank, delivering no cells.
I think that the method in the custom table view class that receives the NSInteger value is this:
- (NSUInteger)numberOfPages {
NSInteger numPages = 0;
if (_delegate)
numPages = [_delegate numberOfColumnsForTableView:self];
return numPages;
}
Do I need to cast the result of someArray.count to an NSInteger?
Here you get the value from array means your array not nil so just debug and check the if condition that its come in that condition or not and what you get from NSLog
- (NSUInteger)numberOfPages {
NSInteger numPages = 0;
if (_delegate){
numPages = [_delegate numberOfColumnsForTableView:self];
NSLog(#"Total record %d",numPages);//what you get here?
}
return numPages;
}
numPages = [_delegate numberOfColumnsForTableView:self];
//self requires an object of type HorizontalTableView
NSMutableArray is editable, where as NSArray is read-only.
NSMutableArray is a subclass of NSArray and responds to messages such as addObject, removeObject and so forth; i.e. it is mutable, like the name says. Instead, NSArray is immutable, i.e. you can't add/remove objects.
In fact converting the value to be returned to the count of an NSArray, as opposed to the count an NSMutableArray fixes the issue. Why? I am not sure why an NSArray's count value is valid but not the NSMutableArray's. Anyone?

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;
}

creating a Mutable array that can be added to in later clicks of the same button?

General noob questions:
(1) How can I create an NSMutable array in a buttonClicked action that I can add more entries to during subsequent clicks of the same button? I always seem to start over with a new array at every click (the array prints with only 1 entry which is the most recent button's tag in an NSLog statement).
I have about 100 buttons (one for each character in my string called "list") generated by a for-loop earlier in my code, and each has been assigned a tag. They are in a scrollview within the view of my ViewController.
I wish to keep track of how many (and which ones) of the buttons have been clicked with the option of removing those entries if they are clicked a second time.
This is what I have so far:
-(void) buttonClicked:(UIButton *)sender
NSMutableArray * theseButtonsHaveBeenClicked = [[NSMutableArray alloc] initWithCapacity: list.length];
NSNumber *sendNum = [NSNumber numberWithInt:sender.tag];
[theseButtonsHaveBeenClicked addObject:sendNum at index:sender.tag];
NSLog(#"%#",theseButtonsHaveBeenClicked);
}
(2) I have read that I may be able to use a plist dictionary but I don't really understand how I would accomplish that in code since I cant type out the items in the dictionary manually (since I don't know which buttons the user will click). Would this be easier if I somehow loaded and replaced the dictionary in a plist file? And how would I do that?
(3) I also have no idea how I should memory manage this since I need to keep updating the array. autorelease?
Thanks for any help you can provide!
Okay, firstly you are creating a locally scoped array that is being re-initialised on every call to buttonClicked:. The variable should be part of the class init cycle.
You will also be better off with an NSMutableDictionary instead of an NSMutableArray. With a dictionary we don't have to specify capacity and we can use the button's tags as dictionary keys.
Here's what you need to do, these three steps always go together: property/synthesize/release. A good one to remember.
//Add property declaration to .h file
#property (nonatomic, retain) NSMutableDictionary * theseButtonsHaveBeenClicked;
//Add the synthesize directive to the top of .m file
#synthesize theseButtonsHaveBeenClicked;
// Add release call to the dealloc method at the bottom of .m file
- (void) dealloc {
self.theseButtonsHaveBeenClicked = nil; // syntactically equiv to [theseButtonsHaveBeenClicked release] but also nulls the pointer
[super dealloc];
}
Next we create a storage object when the class instance is initialised. Add this to your class's init or viewDidLoad method.
self.theseButtonsHaveBeenClicked = [[NSMutableDictionary alloc] dictionary]; // convenience method for creating a dictionary
And your updated buttonClicked: method should look more like this.
-(void) buttonClicked:(UIButton *)sender {
NSNumber *senderTagAsNum = [NSNumber numberWithInt:sender.tag];
NSString *senderTagAsString = [[NSString alloc] initWithFormat:#"%#",senderTagAsNum];
// this block adds to dict on first click, removes if already in dict
if(![self.theseButtonsHaveBeenClicked objectForKey:senderTagAsString]) {
[self.theseButtonsHaveBeenClicked setValue:senderTagAsNum forKey:senderTagAsString];
} else {
[self.theseButtonsHaveBeenClicked removeObjectForKey:senderTagAsString]; }
[senderTagAsString release];
NSLog(#"%#", self.theseButtonsHaveBeenClicked);
}

iphone NSString Array

I declared
NSString *dayinfield[43];
and fill it in
-(void)DrawDemo {
dayinfield[2] = #"hallo";
dayinfield[3] = #"test";
// also i can read it
NSLog (#"show: %#",dayinfield[2]);
//works fine
}
but when i like to read its content in another function (same class)
-(void)ReadData
{
NSLog (#"show: %#",dayinfield[2]);
// I get random infos or “EXC_BAD_ACCESS
}
How do I initialize the NSString Array correct so I can reach its content in each of my functions??
Thanks
chris
If you only assign literals to the array elements, this should not be a problem. But if you use other strings, you have to retain the instances manually when using a C array.
By the way: Objective-C methods start with a lowercase letter.
This would happen if you never initialized the array (or the parts of it you are accessing) - if you haven't called -DrawDemo before -ReadData or used different indices than the ones posted here, the array would simply contain garbage values.
Try to initialize the array contents to nil or #"" in your initializer method and see if the problem persists.
Alternatively consider using a suitable Cocoa container.
It's memory is probably being released before your second call. Assuming you have declared dayinfield as an ivar (and the fact that you don't get bad access all the time) your string aren't properly retained.
Initialise the strings like this:
dayinfield[2] = [[NSString alloc] initWithString:#"hallo"];
dayinfield[3] = [[NSString alloc] initWithString:#"test"];
and you should release them after you're class is being deallocated (See Memory Management Guide).
Also, obviously it depends on what you want to do, but it might be easier if you use NSArray instead of C arrays.
What you have in the OP should work although it is an exercise in sheer masochism to use old school C arrays with objects.
I ran this code:
#interface TestClass : NSObject {
NSString *a[1];
}
- (void) drawDemo;
- (void) readData;
#end
#implementation TestClass
- (void) drawDemo{
a[0]=#"A Zero";
a[1]=#"A One";
}//------------------------------------- (void) drawDemo------------------------------------
- (void) readData{
NSLog(#"a[0]=%#,a[1]=%#",a[0],a[1]);
}//------------------------------------- (void) readData------------------------------------
#end
TestClass *tc=[[TestClass alloc] init];
[tc drawDemo];
[tc readData];
... and got this output:
a[0]=A Zero,a[1]=A One
Your problem is elsewhere in your code. There is no compelling reason to use C arrays with objects. You gain nothing and you have to watch them like a hawk to prevent errors.

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.