Hey guys at Stackoverflow!
I need your help. I am looking for a way to call my method only once after the application has launched and "save" the state of the color of the UIView. At first I will show you my code, that I can explain it in a better way:
-(void)viewWillAppear:(BOOL)animated {
NSArray *colors = [NSArray arrayWithObjects:[UIColor myWhiteColor],[UIColor myBlueColor],[UIColor myCyanColor],[UIColor myGreenColor],[UIColor myOrangeColor],[UIColor myPurpleColor],[UIColor myRedColor],[UIColor myViolettColor],[UIColor myYellowColor], nil];
NSInteger randomIndex = random() % [colors count];
colorTransparentView.backgroundColor = [colors objectAtIndex:randomIndex];
colorTransparentView.opaque = NO;
colorTransparentView.alpha = 1.0;
}
Now I explain you my issue.
As you can see, the code above changes the color of the UIView, every time the "viewWillAppear" method was called. The code randomly changes the color of the UIView(in the .xib) which is linked with an IBOulet to the header file. The problem is that every time I get back to the view I will get a different color.
However, I want to set the random color of the UIView only once the application started. This color should stay until the application was closed from the Multitasking. I can't see any way to solve this. I tried to call the code in the applicationDidFinishedLaunchingWithOptions method, but I wasn't succsessful.
Also I tried the dispatch_once method to call it only once, but as you may think of the color was never called again, so the view got no color the second time loaded.
I really would appreceate if you could help me with this.
Thanks in Advance,
Noah
EDIT:
My header:
#interface ViewController : UIViewController {
IBOutlet UIView *colorTransparentView;
}
#end
What about using a static variable? initialise it with 0 and after changing color in your view will appear. set it to 1 and keep checking it.
int static colortaken = 0;
int static colorindex;
- (void)viewWillAppear:(BOOL)animated
{
NSArray *colors = [NSArray arrayWithObjects:[UIColor myWhiteColor],[UIColor myBlueColor],[UIColor myCyanColor],[UIColor myGreenColor],[UIColor myOrangeColor],[UIColor myPurpleColor],[UIColor myRedColor],[UIColor myViolettColor],[UIColor myYellowColor], nil];
if (colortaken == 0)
{
NSInteger randomIndex = random() % [colors count];
colorindex = randomIndex;
colorTransparentView.backgroundColor = [colors objectAtIndex:randomIndex];
colorTransparentView.opaque = NO;
colorTransparentView.alpha = 1.0;
}
else
{
// do nothin
colorTransparentView.backgroundColor = [colors objectAtIndex:colorindex];
colorTransparentView.opaque = NO;
colorTransparentView.alpha = 1.0;
}
// at end
colortaken = 1;
}
Use dispatch_once. You can read up on singleton approaches in general, but this is the recommended approach.
Related
It might be a simple question yet I could not figure out what I am missing.
In ViewControl.h I declared UIColor
#property (nonatomic, strong) UIColor * myColor;
In ViewControl.m I have a method that do something and return new UIColor
#synthesize myColor = _myColor;
In ViewDidLoad Method
- (void)viewDidLoad
{
myColor = [UIColor RedColor];
}
-(void) ShowColorPopUpView
{
if (!self.wePopoverController)
{
ColorViewController *contentViewController = [[ColorViewController alloc] init];
contentViewController.delegate = self;
self.wePopoverController = [[WEPopoverController alloc] initWithContentViewController:contentViewController];
self.wePopoverController.delegate = self;
self.wePopoverController.passthroughViews = [NSArray arrayWithObject:self.navigationController.navigationBar];
[self.wePopoverController presentPopoverFromRect:self.tvTweetDetails.frame
inView:self.view
permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown)
animated:YES];
} else
{
[self.wePopoverController dismissPopoverAnimated:YES];
self.wePopoverController = nil;
}
}
-(void) colorPopoverControllerDidSelectColor:(NSString *)hexColor
{
_myColor = [GzColors colorFromHex:hexColor];
[self.view setNeedsDisplay];
[self.wePopoverController dismissPopoverAnimated:YES];
self.wePopoverController = nil;
}
- (UIColor *) returnColor
{
return _myColor;
}
My Question starts here: I have two methods to change a textview font and background color
- (IBAction)btnFontColorPopUpMenu:(id)sender
{
[self ShowColorPopUpView];
tvTweetDetails.textColor = [self returnColor];
}
- (IBAction)btnTextViewBackGroundColor:(id)sender
{
[self ShowColorPopUpView];
tvTweetDetails.backgroundColor = [self returnColor];
}
The issue now is when I call the method it return it returns RED and if I call it again it returns the the BlackColor.
How Can I call the method and change the Color to the new one and then return it. I want to get the Black color directly.
I want to execute the method first then return the color but what happens is assign the color before execute the method.
I hope I made it the Question Clear.
Okay, I'll take a whack at this.
I suspect you are doing some kind of presentViewController:... method in your color changer method. That's great, but it has implications. The method you call that in continues to execute during that presentation. That means it may return, etc.
This is where the concept of delegates comes in. You may benefit from restructuring the data flows here a bit.
What I suggest (if I am correct about the presentation of a color picker UI) is that you make the following changes:
Create a #protocol ColorPickerDelegate with one method: -(void) userChoseColor:(UIColor *) color
Add a #property (weak) id<ColorPickerDelegate> delegate to your color picker view controller
make your VC here implement that protocol
Inside the delegate method, set your local property
Implement a custom setter for the local propert, and update the background color whenever the color changes.
In my viewDidLoad method of my iPhone app I have the following code:
zombie[i].animationImages = zombieImages;
zombie[i].animationDuration = 0.8/zombieSpeed[i];
zombie[i].animationRepeatCount = -1;
[zombie[i] startAnimating];
Later on in the app the following code is called:
[zombie[i] stopAnimating];
zombie[i] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"zh.png"]];
zombie[i].animationImages = flyingZombieImages;
zombie[i].animationDuration = 0.8/zombieSpeed[i];
zombie[i].animationRepeatCount = -1;
[zombie[i] startAnimating];
This causes the app to crash, with EXC_BAD_ACCESS on the line zombie[i].animationImages = flyingZombieImages;
flyingZombieImages is initialized with the following code: (zombieImages is initialized the same way)
NSMutableArray *flyingZombieImages = [NSMutableArray array];
for (NSUInteger i=1; i <= 29; i++) {
NSString *imageName = [NSString stringWithFormat:#"flzom%d.png", i];
[flyingZombieImages addObject:[UIImage imageNamed:imageName]];
}
Why is this happening? Is there a workaround?
As Dima mentioned flyingZombieImages is likely not initialized properly, which is causing the crash. However, there is another problem as well when you create the new instances of UIImageView:
zombie[i] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"zh.png"]];
At this point you already have a reference to the old UIImageView stored in this variable. You are losing the reference to it and most likely will leak its memory. You also would want to remove the old UIImageView from the view hierarchy and add the new one.
A better way is instead to use the original UIImageView and change its image by replacing this line with:
zombie[i].image = [UIImage imageNamed:#"zh.png"];
I've been trying to figure out how to have a UIImageView with a next and previous button which when clicked will go to the next or previous image in the array. So far, here's what I have.
In my .h file I have declared:
IBOutlet UIImageView *imageView;
NSArray *imageArray;
And I also added:
-(IBAction) next;
In the .m file I have:
-(void) viewDidLoad;
{
imageArray = [[NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
nil] retain];
}
Now here is where I'm struggling. I have the IBAction defined as follows in my .m:
-(IBAction)next
{
if (currentImage + 1 == [imageArray count])
{
currentImage = 0;
}
UIImage *img = [imageArray objectAtIndex:currentImage];
[imageView setImage:img];
currentImage++;
}
My problem is that I do not know where to define the currentImage index integer or how to define it. Is it in the header? The implementation? And how exactly do I declare it?
To be honest I'm not even 100% sure the code I currently have is right, although I think if I can define the index, it will work.
Any advice?
This is how I would do it. (I've changed the name of a few instance variables: currentImage sounds like it could be a pointer to an image (UIImage *) rather than just an integer value; adding Index to the end makes that more clear. It may be obvious now that it's an integer, but when you revisit this code (or other code you write) in a month, it may be less obvious; or maybe that's just me)...
MDSlideshowController.h:
#import <UIKit/UIKit.h>
#class MDBilboBaggins;
#interface MDSlideshowController : NSObject {
IBOutlet UIImageView *imageView;
NSArray *imageArray;
NSUInteger currentImageIndex;
BOOL someOtherVariable;
MDBilboBaggins *bilboBaggins;
// keep adding more instance variables as needed
}
- (IBAction)previous:(id)sender;
- (IBAction)next:(id)sender;
#end
MDSlideshowController.m:
#import "MDSlideshowController.h"
#import "MDBilboBaggins.h"
// you could perhaps define currentImageIndex here, but see notes below:
// NSUInteger currentImageIndex = 0;
#implementation MDSlideshowController
// `currentImageIndex` is automatically initialized to 0 during init
// `someOtherVariable` is automatically initialized to 0 (NO) during init
-(void) viewDidLoad
{
imageArray = [[NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
nil] retain];
[imageView setImage:[imageArray
objectAtIndex:currentImageIndex]];
}
- (IBAction)previous:(id)sender {
if (currentImageIndex == 0) {
currentImageIndex = [imageArray count] - 1;
} else {
currentImageIndex--;
}
[imageView setImage:[imageArray objectAtIndex:currentImageIndex]];
}
- (IBAction)next:(id)sender {
if (currentImageIndex + 1 >= [imageArray count]) {
currentImageIndex = 0;
} else {
currentImageIndex++;
}
[imageView setImage:[imageArray objectAtIndex:currentImageIndex]];
}
#end
Basically, you put instance variables right underneath the ones you've already defined. They can be of almost any type. You can use the types Cocoa Touch knows about, or classes you make yourself. In this example, I said that there was a special class named MDBilboBaggins by using the #class MDBilboBaggins statement. Then, I add the #import "MDBilboBaggins.h" part in the .m file: this can help speed up compile times.
As I mentioned in the comment, you could perhaps define the currentImageIndex variable inside the .m file, however, it would be a static variable that is common to, and shared, by all instances of the class. This can be useful in some situations, but create issues in others. For example, imagine we have 2 slideshow controllers, each with different images created and showing slides in 2 different windows. If they were modifying a shared currentImageIndex variable, they'd mess each other up if you would switch between them and start clicking Previous and Next indiscriminately. That's why in this case it might make more sense to just make it an instance variable by defining it other your other instance variables in the .h file.
[EDIT] Regarding the :(id)sender parameter: in this example, it wasn't used at all, I generally do it out of habit, since in some circumstances, it can save a lot of code, and simplify things dramatically. For example, say you had 9 different buttons and you wanted each button to load a specific image (or perform a specific operation). Now, you could define 9 separate methods like - (IBAction)button1Clicked;, or you could do it the easy way and just define a single - (IBAction)loadImage:(id)sender method. In your nib file, you would give each button a different tag (an NSInteger value), like 1 − 9. Then in your single method you could do this:
- (IBAction)loadImage:(id)sender {
NSInteger buttonTag = [(NSButton *)sender tag];
[imageView setImage:[UIImage imageNamed:
[NSString stringWithFormat:#"image%ld.png",buttonTag]]];
}
In this case, sender is the object that sends the message, which would be the button that was clicked on. Though admittedly a contrived example, by providing that one additional parameter, I probably saved 100 lines of needless code and complexity of having 9 separate methods.
[EDIT #2] Replaced the one pseudo-coded (written in Safari) next: method with actual code from one of my apps that I know works.
Hope this helps...
you need to declare the currentindex in the header like so:
NSInteger currentImage;
This way the value is saved throughout the views lifetime
I have 4 UITextFields that I'm dynamically creating, in the viewDidLoad, which works good. I want to reference those objects when the UISlider value changes. Right now I'm storing those objects in a NSMutableArray and accessing them like so from the sliderChanged method:
NSInteger labelIndex = [newText intValue];
labelIndex--;
NSUInteger firstValue = (int)0;
NSMutableArray *holeArray = [pointsArray objectAtIndex:labelIndex];
UITextField *textField = [textFieldArray objectAtIndex:firstValue];
NSString *newLabel1Text = [[NSString alloc] initWithString:[[holeArray objectAtIndex:firstValue] stringValue]];
[textField setText: newLabel1Text];
[newLabel1Text release];
Everything is working good, but the program crashes on the setText: method. The last message I get from the program is: [UILabel drawTextInRect:] and then I get a EXC_BAD_ACCESS failure.
I want to be able to acces that dynamically created UITextField, but I must be going about it the wrong way.
Thanks!
Uh, yea, you create a text field, but you aren't displaying the field itself, just creating it.
If you want to do what I think you want to do, I would just do if statements.
ex.
if (firstValue == 1)
{
fieldone.text = #"whatever";
}
else if (firstValue == 2)
{
fieldtwo.text = #"whatever";
}
I have problem with customizing each page using pagecontrol and UIScrollView.
I'm customizing Page Control from Apple.
Basically I would like to have each page different with text and image alternately on different page. Page 1 will have all text, Page 2 will have just images, Page 3 will have all text and goes on.
This is original code:
// Set the label and background color when the view has finished loading.
- (void)viewDidLoad {
pageNumberLabel.text = [NSString stringWithFormat:#"Page %d", pageNumber + 1];
self.view.backgroundColor = [MyViewController pageControlColorWithIndex:pageNumber];
}
As you can see, this code shows only Page 1, Page 2 etc as you scroll right.
I tried to put in this new code but that didn't make any difference. There's no error.
I know this is pretty simple code. I don't why it doesn't work.
I declare pageText as UILabel.
// Set the label and background color when the view has finished loading.
- (void)viewDidLoad {
pageNumberLabel.text = [NSString stringWithFormat:#"Page %d", pageNumber + 1];
self.view.backgroundColor = [MyViewController pageControlColorWithIndex:pageNumber];
if (pageNumber == 1) {
pageText.text = #"Text in page 1";
}
if (pageNumber == 2) {
pageText.text = #"Image in page 2";
}
if (pageNumber == 3) {
pageText.text = #"Text in page 3";
}
}
I don't know why it doesn't work. Also if you have better way to do it, let me know. Thanks.
I downloaded the sample, added the following lines to the MyViewController.h
IBOutlet UILabel *pageText;
#property (nonatomic, retain) UILabel *pageText;
In the MyViewController.m I added the #synthesize pageText; line and your viewDidLoad contents.
I opened the MyView.xib/en file in interface builder and connected the new label. Compiled and ran and it worked for the most part. Only thing that didn't seem right was that it was a page behind. so I rewrote it to just handle odd or even pages appropriately.
- (void)viewDidLoad {
pageNumberLabel.text = [NSString stringWithFormat:#"Page %d", pageNumber + 1];
self.view.backgroundColor = [MyViewController pageControlColorWithIndex:pageNumber];
if (pageNumber % 2) {
pageText.text = [NSString stringWithFormat:#"Image in page %d", pageNumber + 1];
} else {
pageText.text = [NSString stringWithFormat:#"Text in page %d", pageNumber +1];
}
}
This answer will have very little code, as I have no distinct example. You basically want to have some array of pages, which holds a view (or view controller) for each page. There is no necessity that each view/controller in the array be the same (though you should have it be all views or all view controllers, not both). Once you have that, you can load something distinct depending on which page you're loading.
Does that make sense?
try to download this project from SVN repo. I've been unable to finish the documentation but check out IGUIScrollViewElements ... there is a short example for IGUIScrollViewImage and the code is quite similar ... I'll do my best to finish examples for the remaining ones asap ...
http://code.google.com/p/iphone-guru-uilibrary/