How to change an image using an array in xcode (objective C) - ios

So I'm new Objective C and I'm building my first app, although I'm stuck on a particular function for my character creation feature.
I have added 'back' & 'forward' buttons and these are meant to move between the selections that I have (e.g. shirt images).
I have 4 different choices for the shirt and was wondering how I would add these 4 images into an array that I would then be able to use with the 'back' and 'forward' buttons in order to navigate between the choices.
Any help would be appreciated.

Are you using Swift or Objective-C? I'll assume Objective-C. Ok. So you got it. Now you just got to implement it. You'll have to initialize a new array with the four images, arrayWithObjects: or initWithObjects:. You'll have to have a UIImageView drawn on the screen, added as a subview (UIView's addSubview:). Then you may want to keep a disposable "counter" private ivar (could be a property too if you wanted) that keeps track of the index of the current image being displayed (declared in your .m, .h is fine too). You could do this or you could have a dynamic getter method that returns the index based on the method objectAtIndex: on your array with your image view's image. When the user clicks forward or back the counter is updated (if it's an ivar and not a getter) and the image view's image is updated based on the new counter value (eg. self.imageView.image = imageArray[counter]) or something like that. You could disable the forward/back buttons if the counter value is on the edge of the array's count property. When the view is initially loaded you could load the image view's image based on the current counter value which would be 0 by default.
In this answer, I did not write the code for you. I showed you snippets of stuff and gave you different potential alternatives to write your program. You'll have to put it together yourself and choose what you're most comfortable with.

In Objective-C, there are two classes of objects: Primitives (like NSInteger, int, char) and everything else. Non primitives can be stored in NSArrays. NSArrays are immutable, meaning that you cannot change them once they have been created. However, there is a sub-class of NSArrays called NSMutableArray. You can add and delete objects to these and sort them if you want. So if you have four
UIImage objects, you could do something like this:
NSMutableArray* images = [NSMutableArray new];
[images addObject:image1];
[images addObject:image2];
[images addObject:image3];
[images addObject:image4];
....
The objects are added in order, so you can retrieve the second image (for example) like this:
UIImage* second = [images objectAtIndex:1];
(Indexing is zero-based)

Related

Release Dynamic Objects at a later state

I have the following question.
Lets say i have a UIViewController Class named "ModuleViewController" which contains multiple dynamically created UIButtons and multiple dynamically created Mpmovieplayercontrollers. Each of these objects have their Callback functions, contained in the "ModuleViewController" Class. One Call Back for all the UIButtons and one for all The Mpmovieplayercontrollers.
Now i want to add multiple "ModuleViewController" Class instances inside a UIScrollview.
I do not use ARC. If i release these objects after i allocate them and initialize them inside my "ModuleViewController" Class, the Buttons and the Videos do not play or rhe Application Crashs.
Currently my solution is to have an NSMutableArray to store their pointers when they are created, and then release them when i release the "ModuleViewController" Class at a later state. (e.x. Release the "ModuleViewController" Class when it is off screen from the viewport of the UIScrollview)
For example. If my array which holds the pointers is "objectsRetained"
// Creating the Array of fPointers on ViewDidLoad
NSMutableArray *objectsRetained = [[NSMutableArray alloc] init];
.
.
// Add Object Pointer inside the array to release it at later state
[objectsRetained addObject:[NSValue valueWithPointer: myObject]];
This solutions works but when i analyze my application, it shows that there is a posible Memory Leak in this area.
Is there another way to solve this?
First, use ARC.
But in this case, the problem seems to be in your extra NSValue wrapper. Just put the buttons in an NS(Mutable)Array directly. The array will retain the buttons for you. In -dealloc, call [buttons release]. That will release the buttons. There is no need to bundle these things into value objects.
And then switch to ARC. (But the approach is completely the same; you just don't need dealloc then.)

iOS: How to handle icons selectable by user? (saving/loading etc.)

I'm working on my first more complex app and couldn't find a solution to this one. I have loaded about 64 icons into my app. For a table view, a user can assign to each cell one of these icons. Basically when he edits the cell he gets to a new UIView with all the 64 icons. The currently chosen icon should have a border and if he clicks a different one, the border should move and the icon assigned to that selected item in the tableview.
My problems are now:
a) How do I load these 64 icons into my view? I've created the view with all the UIImageViews, but how do I load them into these imageviews? Where are they saved if I copy them just to my directory and how do I access them?
b) Is there an easier way than placing 64 different UIViews into this view manually and linking them up with IBOutles?
Your problem could easily be resolved using UICollectionView . A UICollectionView just acts like a UITableView .
Go through the link in order to find more about UICollection
http://skeuo.com/uicollectionview-custom-layout-tutorial
Using UICollection view you just need the pass the image object saved in your Array
That's a lot of questions on a wide variety of topics.
How do I load icons/images?
UIImage *image = [UIImage imageNamed:#"fubar.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
If you just copy images in your project they are part of the main bundle and for the most part you and pretty much ignore where they are saved. It's pretty easy to access them. (see above)
Is there an "easier way"... well, you'd have to give us a way if you want to know if there is an easier way. However I think a simple naming convention and a loop would be workable.
NSMutableArray *icons = [NSMutableArray array];
NSString *iconName;
UIImage *image;
UIImageView *imageView; = [[UIImageView alloc] initWithImage:image];
for (int count=0 ; count < 65 ; count++) {
iconName = [NSString stringWithFormat:#"icon%d.png", count];
image = [UIImage imageNamed:iconName];
[icons addObject:image];
}
Then you would use your icons array as the basis of your UITableView. About that though. You might want to look into using a UICollectionView instead. It's like a table, but it's a grid of items instead of just rows. It would lend itself better to a large set of images.
As for how you copy the images into the views, both your UITableView and your UICollectionView have methods where they "ask" for the data and give you a position. Based on the position information you just set the it asks for and it will handle the rest. It might look something like
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
// ...
// remembering 'icons' is our array of image data
cell.imageView.image = icons[indexPath.row];
// ...
}
Edit from Comments: How to tell if a file exists in the app bundle? (my answer is just a cut/paste)
[[NSFileManager defaultManager] fileExistsAtPath:pathAndFileName];
You would have to do this in code. I would suggest you put all your filenames in NSArray, then iterate through it and with each step create a UIImageView on your ViewController programmatically. I suggest though that you subclass UIButton so it is "selected" when you tap it and you can then put any image into it.
you can use gridView a open source component here is the link
GridView
Also to detect you can assign tag to each imageView like from 0 to 63 then when user choose 0th image you can assign that tag to a local variable so that next time when user views grid you can identify that user has previously chose 0th index image. I hope it helps you.

Specific UIImages and UIImageView help on theory?

I've been trying to figure out UIImage for some time now. I've been trying to figure out an approach to having one view the 'Main Game View' and showing either 2/3/4 different images depending on the 'level' variable. I'm just trying to be sure of logic. So for example level 1 would display 4 pictures and level 2 might display 3 different pictures. I don't want to hinder performance of the app but because the game is to be played offline and archiving won't make much of a difference all the images (several hundred optimised images) are being stored locally in the main app bundle.
I'm just wondering if my logic for trying to implement this so far is sound or not. For level 1 I would implement the 4 UIImageViews needed and initialise them with images, then display them on screen at set positions. I would then preload the next levels images using GCD. When a continue button is pressed I will set the UIImages and the UIImageViews to nil and display level 2's (or the next level) on screen.
I'm not confident in my approach and was wondering if there was something that would make it simpler or something I've missed or even if in practice it will work accordingly to the theory.
Thank you in advance for you time and any help.
Sorry if this is unclear.
I'm assuming you use a single view controller class for all your levels and load the levels from some .plist file or other format.
Don't bother using GCD. Loading 4 images once per level during loading costs practically nothing.
If all you need to do is have 2-4 images on the screen for each level (in addition to any other level elements), simply create 4 UIImageView instances and add them to your view. Then when you load a level, create new UIImage objects from the required image files and set your UIImageViews' image property to them. The UIImage objects of the old level will be released and deallocated at that moment, since you (and the UIImageViews) don't have a strong reference to them anymore.
Pseudo implementation:
- (void)loadLevel:(int)levelNumber {
// Assuming you have your image views in an array imageViews.
// Determine the image files required for this level.
// Put them into an array imageNames.
for (int i = 0; i < 4; i++) {
if (imageNames.count < i) {
UIImage *image = [UIImage imageNamed:imageNames[i]];
[self.imageViews[i] setImage:image];
} else {
[self.imageViews[i] setImage:nil];
}
}

Is it possible to convert description (String representation) of some object to an object of some class?

I need to pass a parameter to IBAction (but it has only sender(id) - UIButton in my case), so I'm wondering if it possible to convert description of some object to an object. Right now I'm passing parameter as button's [titleLabel text]:
[[button titleLabel]setText:[someObject description]];
And in IBAction I'm getting description:
- (IBAction)AddToCalendarEvent:(id)sender {
NSString * description = [[sender titleLabel]text];
NSLog(#"description is %#", desc);
}
And now I want to convert this description to an object. Is it possible?
UPD
I'm dynamically filling table view with cells. Each cell has four buttons and I want these buttons to keep some object as parameter to pass to IBAction.
I think the best solution for you, based on what I've read and currently understand about your problem, is to maintain an array (or some other appropriate data structure) of your buttons on your View Controller. Then, in your action method that each button calls when it is tapped, you can search your array of buttons for the sender of your action method. Then, once you've figured out which button has been tapped, you can use that to then find whatever data you're looking for in your data model. You should apply this solution to your situation and it will probably end up looking a bit different, but the basic idea is sound. You should avoid maintaining state in your view (in this case your buttons) and it looks like you're approaching that from your description of the problem.
You definitely don't won't to convert in this way.
A simple option is to set the tag of each UIButton to a unique integer, and store an array of the objects you need to look up:
- (IBAction)AddToCalendarEvent:(id)sender {
NSInteger senderTag = [sender tag];
NSLog(#"Sender index = %d", senderTag);
// Use this tag as an index to the array.
}
A more complicated route is to subclass UIButton (usually not recommended), to store the associated data with each UIButton. Then you can look it up, once again from the sender.

XCode: Add multiple buttons programmatically with specific names and animate

I just read this post about adding buttons with a loop programmatically.
I want to do the same thing, but do it with a name for each one, and animate them the same way. Is this a good idea, or should I just copy the same line of code for each button?
Further, I'd like to add a number of buttons (say four) from a list of names (greater than four) and pick them randomly. The catch is, I need them to be named properly and pull images associated with each name. Any ideas?
Thanks SO community!
As I see it, you should make a property list (.plist) with the array of buttons info - for each button there will be text to display, pic to display and action (method name or something).
You can generate four different random numbers in range [0, [buttonArray length]] and then generate your buttons in the loop for each selected number.
I guess, you need something like buttonFactory with method
-(UIButton*) makeButtonWithInfo(NSDictionary*)info
where name, picture adress, action etc. stored in info (you custom type buttonInfo if it is complicated).
Update:
Create new .plist in Xcode (resources/PropertyList) and fill it like this:
Read it in your code with
NSArray* buttonsArray = [NSArray arrayWithContentsOfFile:myPlist.plist];
There will be dictionaries with button info in this array.
Read in Xcode help about NSArray, NSDictionary and UIButton classes and implement your logic.

Resources