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;
}
Related
I'm having trouble making the sections in a UITableView. I've looked at the documentation for UILocalizedIndexedCollation as well as this sample code project:
https://developer.apple.com/library/ios/#samplecode/TableViewSuite/Listings/3_SimpleIndexedTableView_Classes_RootViewController_m.html#//apple_ref/doc/uid/DTS40007318-3_SimpleIndexedTableView_Classes_RootViewController_m-DontLinkElementID_18
What I have below is basically a straight copy/paste from the sample project. However, the sample project uses a custom object (TimeZoneWrapper.h) and then places the object in the correct section based on the object's instance variable (TimeZoneWrapper.localeName). However, I'm not using custom objects. I'm using just a bunch of regular NSStrings. So my question is what method on NSString should I pass to the #selector() to compare and place the string in the correct section array?
Currently, I'm calling NSString's copy method as a temporary hack to get things working (which it does), but I'm not sure if this is correct. A little explanation would be much appreciated!
- (void)configureSections {
// Get the current collation and keep a reference to it.
self.collation = [UILocalizedIndexedCollation currentCollation];
NSInteger index, sectionTitlesCount = [[collation sectionTitles] count]; // sectionTitles are A, B, C, etc.
NSMutableArray *newSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
// Set up the sections array: elements are mutable arrays that will contain the locations for that section.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[newSectionsArray addObject:array];
}
// Segregate the loctions into the appropriate arrays.
for (NSString *location in locationList) {
// Ask the collation which section number the location belongs in, based on its locale name.
NSInteger sectionNumber = [collation sectionForObject:location collationStringSelector:#selector(/* what do I put here? */)];
// Get the array for the section.
NSMutableArray *sectionLocations = [newSectionsArray objectAtIndex:sectionNumber];
// Add the location to the section.
[sectionLocations addObject:location];
}
// Now that all the data's in place, each section array needs to be sorted.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *locationsArrayForSection = [newSectionsArray objectAtIndex:index];
// If the table view or its contents were editable, you would make a mutable copy here.
NSArray *sortedLocationsArrayForSection = [collation sortedArrayFromArray:locationsArrayForSection collationStringSelector:#selector(/* what do I put here */)];
// Replace the existing array with the sorted array.
[newSectionsArray replaceObjectAtIndex:index withObject:sortedLocationsArrayForSection];
}
self.sectionsArray = newSectionsArray;
}
Thanks in advance!
You should use #selector(self).
Using #selector(copy) will cause memory leaks in your project
is is possible to access objects using variables in a FOR statement?
Say i have declared:
UIImageView *UIImageView0;
UIImageView *UIImageView1;
UIImageView *UIImageView2;
and i have 3 objects in an array and i call a FOR statement if x in the array is equal to 2 i want it to add the value of x to the UIImageView name like UIImageView1 etc
I have tried:
for (int x=0; x<[theArray count]; x++) {
UIImageView[x].image = etc....
}
but it gives me a error on UIImageView[x]
subscript requires size of interface 'UIImageView'
any ideas? or is it even possible with a UIImageView?
Thanks
You don't have three elements in an array, though; you have three independent variables with similar names. If you created an actual array, containing the values of the three variables, then you could use the for loop -- and in fact, the syntax would be just as you've shown (using the actual name of the array variable, of course.)
You could say
UIImageView * views[3] = {UIImageView0, UIImageView1, UIImageView2};
and then use, for example, views[i].image in your loop.
In order to put your UIImageView into an array you need to create an instance NSMutableArray (for instance)
The above code does not show any array, instead you have three ivars
UIImageView *UIImageView0;
UIImageView *UIImageView1;
UIImageView *UIImageView2;
and to access those you would use the name, not an array.
If you however put them into an NSMutableArray you can access them using
NSMutableArray array = [[NSMutableArray alloc]
initWithObjects:UIImageView0, UIImageView1, UIImageView2, nil];
[array objectAtIndex:i ]; // where i is 0,1 or 2
...
[array release];
You can put your UIImageView to another array, and get the UIImageView from that array.
NSArray *imagesArray = #[imageView0, ...]
for(size_t i = 0; i<theArray.count; i++)
{
UIImageView *imageView = [imagesArray objectAtIndex:i];
}
Or you can use the "tag" property of UIView like:
UIImageView *image0 = ...;
image0.tag = 100; //or 0 or something else
[self.view addSubview:image0];
And then get the UIImageView by tag in your FOR statement:
for(size_t i = 0; i<theArray.count; i++)
{
UIImageView *imageView = [self.view viewWithTag:100+i];
}
Basically my view controller has 49 different instance variables of class CircleView (called circleView1, circleView2, ..., circleView49). The CircleView class is a simple subclass of UIImageView and basically returns a circle picture when initialized.
Here is what I am trying to do:
In my implementation for the view controller, I want to be able to select the instance variable using a string, for example let's say I generate a random integer i between 1 and 49, lets say it's 5. I would like to be able to build an NSString using something like [NSString stringWithFormat #"circleView%i",i]; and somehow reach the actual circleView5 instance variable. Is this possible?
P.S. I'm looking for something in the lines of NSClassFromString, but which applies to instance variables or objects.
KVC is your friend. Assuming you have a string with the name of the circleView in it,
NSString *myCircle = [NSString stringWithFormat:#"circleView%i", i];
you access that property on the controller using KVC:
CircleView *theCircle = [self valueForKey:myCircle];
On a side note, you should consider redesigning the object heirarchary; this will be very difficult to maintain, and there are certainly better ways to do it (an array with the CircleView's accessed by index would be my first choice).
Instead of having a pile of variables and trying to access them via a string, use an array (either a primitive C array or an NSArray: I'll demo with an NSMutableArray). Declare a NSMutableArray *circleViews; in your class like you did the circleViewN instances. In your initializer, instead of a bunch of circleViewN = [[CircleView alloc] init];, you'd have something like:
circleViews = [NSMutableArray arrayWithCapacity:50];
for(int i=0; i<50; i++)
[circleViews addObject:[[[CircleView alloc] init] autorelease]];
Then you can access the desired circle with your random int i with [circleViews objectAtIndex:i];.
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.
Is it possible to have a variable outlet name?.
For example you have 10 labels (perhaps seats on bus). each has an outlet, seat1 seat2 etc.
Is it possible to have a for loop
that concatenates #"seat" to the increment integer. So that I can access seat1, seat2 outlet without having to specify it individually.
This doesn’t work but makes it a bit clearer what I am trying to achieve.
int i;
for (i = 0; i < [seatarray count]; i++)
{
[#”seat” stringByAppendingString[ i stringValue]] = #””;
}
Starting iOS4 you can use IBOutletCollection which allows to connect multiple instances to a single outlet which represents an array of objects, e.g. IBOutletCollection which can store UILabels only:
#property (nonatomic, retain) IBOutletCollection(UILabel) NSArray *seats;
It might be easier to simply create the array yourself at load time:
self.seatarray = [NSArray arrayWithObjects:seat1, seat2, ..., seatN, nil];
You should be able to do that with key-value coding, something like (untested code)
for (int i = 0; i != 10; ++i) { [self setValue:#"foo" forKey:[#"seat" stringByAppendingFormat:#"%d", i]]; }