Reloading a non-table view (iOS) - ios

I'm working on a painting app, and I want to user to be able to switch through paintings that are saved as PNGs to the documents directory. I've made an IBAction that does this:
-(IBAction)switchPage:(id)sender{
if ([sender tag] ==1)
{
currentImage=currentImage-1;
}
else
{
currentImage++;
}
[[NSUserDefaults standardUserDefaults] setInteger:currentImage forKey:#"currentDoc"];
[self.view setNeedsDisplay];
}
Just to let you know, I have 2 buttons, a back and forward, and they're connected to the same IBAction that's pasted above. The back button has a tag of 1, and the forward button doesn't have a tag. currentImage is an int that is used to set an image's name, so if currentImage =1, then it would set the image to image1. But that's not what I'm having trouble with, I'm having trouble "reloading" the view. I'm using setNeedsDisplay, but it's not working, and I know that reloadData is only for UITables, so what else could I use?
I've been searching for an answer, but none of the existing questions about this don't have a clear answer, or are under different circumstances.
Thanks for your time and/or dealing with a stupid question, as I'm new to Xcode.
-Karl

I see no view code in your post.
Assuming you have a UIImageView that is displaying the image you would just do:
myImageView.image = whateverUIImage;

Related

Thread issue where updating a label make a UIImageview invisible

I have a situation that is confusing me lots. I have a class that has 2 completely separate things: An animated UIImage and a UILabel. They have different outlets, are not connected.
When the app runs, it does this:
dispatch_async(dispatch_get_main_queue(), ^{
[self.monsterMachine setHidden:NO]; //monsterMachine is UIImageView
[self.monsterMachine startAnimating];
});
but then when I do this:
[self.futText setText:#"blah"]; // is UILabel
it causes the monsterMachine UIImageView to not animate anymore. Things I have found:
Right after I setText:#blah" I can use NSLog to watch and see that self.monsterMachine.isAnimated suddenly goes from 1 to 0, ie from YES to NO.
If self.futText is ALREADY saying "blah", then I can run setText:#"blah" on it as many times as I want and nothing happens, it is ONLY when I change it to some value other than blah that UIImageView stops animating and disappears
If I don't use main_queue to show and animate monsterMachine, it won't display at ALL, so how do I diagnose or fix this?
That's weird it works for me perfect. Did you call [self.futText setText:#"blah"]; in main queue also?
Here is a small answer to why setting text #"blah" won't stops the animation:
Strings like #"blah" are stored in stacks which have the same reference as long as they have the same context. In this case [self.futText setText:#"blah"] will do nothing because the internal implementions are like:
void setText:(NSString*) text {
if ( _text == text ) then return;//if reference is the same then do nothing
_text = text;
some rendering..
}

How to tell if a button is pressed at a certain time

I have a button with an image, and after a little while the button image will change, then change back after a few seconds. I want to be able to tell if the button is clicked while the image is different. thanks!
You have several options, but I'll detail two of them. The first is more self-contained and foolproof, but the second is arguably easier to read and understand.
Check the background image
The easiest way to do this would probably be to just test against the image itself. The image changes from time to time, but you don't really care when the button is pressed, you just care which background is visible when it is.
In other words, all you really need to know is whether the button's background is the MainBackground or the AlternateBackground, so when the button is pressed, you can simply check which one it is.
Try something like this, for when the button is pressed:
-(void)buttonPressed:(UIButton*)sender {
UIImage *mainBackground = [UIImage imageNamed:#"YOUR_IMAGE_NAME"];
NSData *imgdata1 = UIImagePNGRepresentation(sender.image);
NSData *imgdata2 = UIImagePNGRepresentation(mainBackground);
if ([imgdata1 isEqualToData:imgdata2]) {
// The button's background is the MainBackground, do one thing
} else {
// The button's background is the AlternateBackground, do another thing
}
}
Keep track of which image is currently displayed
Alternatively, you could have a BOOL value flip whenever the image's background is changed. Something like...
#property BOOL isMainBackground;
...in your H file, and then whenever you set the button's background image, you also set self.isMainBackground = YES; or self.isMainBackground = NO;
Then, your method for the button press would look something like this:
-(void)buttonPressed:(UIButton*)sender {
if (self.isMainBackground) {
// The button's background is the MainBackground, do one thing
} else {
// The button's background is the AlternateBackground, do another thing
}
}

Stuck with UIActionSheetPicker , iOS

This is going to be a very targeted question , as its for people that have actually used the UIActionSheetPicker before.
I used it in my iphone applications and everything worked great , but now that i tried to implement it on my ipad i experienced some problems.
The main problem is that on ipad the picker appears as a "bubble" or "info window" if you prefer , which points at the spot where it was called , like a button a text field etc.
Below is an example of it :
You can see that the "info window" is pointing at the animals button.
In my application i have 4 different buttons. 2 are in the top side of the screen and 2 at the bottom.
Those who are at the bottom , call the picker very well and the picker appears on top of the buttons pointing down on them.
However , the ones on the top of the screen (almost like the one in the image) when they call the picker the picker appears much lower on the screen and doesnt point at them as it should ...
I mean i expected to appear just under the buttons pointing at them (like in the image), but they are almost in the center of the screen pointing nowhere..
Any ideas? Has someone experienced this before?
EDIT
In the beginning , i was calling the ActionSheetPicker inside the buttons action like this:
- (IBAction)selectTopic:(UIControl *)sender {
[ActionSheetStringPicker showPickerWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Now i am trying to call it like this:
- (IBAction)selectTopic:(UIControl *)sender {
ActionSheetStringPicker *thePicker = [[ActionSheetStringPicker alloc] initWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
thePicker.presentFromRect = topicField.frame;
[thePicker showActionSheetPicker];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Where topicField is my TextField.
Sadly the result is the same. Even now that i am specifying where i want the arrow to point , the picker is called 300 pixels down.
The strange thing is though that even with another other button that is a bit lower than the previous the picker is again exactly 300 pixels down.
EDIT2
After noticing that the picker shows 300 pixels down , i decided to manually make it show 300pixels up , to point exactly on my button.
I used the following code :
- (IBAction)selectTopic:(UIControl *)sender {
//[ActionSheetStringPicker showPickerWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
ActionSheetStringPicker *thePicker = [[ActionSheetStringPicker alloc] initWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
CGRect pickerFrame = topicField.frame;
pickerFrame.size.height -= 300;
thePicker.presentFromRect = pickerFrame;
[thePicker showActionSheetPicker];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Amazingly the button once again appears in the same position 300pixels down. I start to believe that this one may not be the property to alter the position of the picker.
Any ideas ?
Setting the presentFromRect in your calling code won't make a difference since it will be reset based on the sender within the ActionSheetPicker code, instead you are going to need to modify the source code of the library.
The following (unmerged) commit on github should resolve the issue On iPad, set the popover to point properly at its container.
Basically within the AbstractActionSheetPicker.m file modify the - (void)presentPickerForView:(UIView *)aView method like the following
- (void)presentPickerForView:(UIView *)aView {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.presentFromRect = CGRectMake(0, 0, self.containerView.frame.size.width, self.containerView.frame.size.height);
[self configureAndPresentPopoverForView:aView];
}
else {
self.presentFromRect = aView.frame;
[self configureAndPresentActionSheetForView:aView];
}
}
After a brief look at the code, I would say that you want to make sure that the presentFromRect on the ActionPicker object is in the coordinates of the container that you are passing in on the init. For instance if I had one big view that contained a button:
This is untested:
UIView* someBigView = ... // get the big view
UIButton* someButton = ... // get the button that the big view contains
ActionSheetDatePicker* thePicker = [[ActionSheetDatePicker alloc] initWithTitle:#"Some Title"
datePickerMode:UIDatePickerModeDate
selectedDate:[NSDate date]
target:self
action:#selector(someMethod:)
origin:someBigView];
//the arrow should be pointing at the button
thePicker.presentFromRect = someButton.frame;
[thePicker showActionSheetPicker];
In my opinion, this library has a pretty big flaw in the fact that it takes an origin parameter that can be a button item or a container. It requires that you look at the source to understand it, instead of being (somewhat) obvious from the interface.

Prevent choosing of certain objects in NSMutableArray?

I am kind of in a pickle here since I have tried many things to accomplish this and have failed.
What I want to do: I have a NSString in my app which is the answer to a question to a round in a quiz. My answers are stored in a NSMutableArray. These answers are chosen at random. I have 4 buttons in my app that are options (possible answers) for the round. I don't want to have multiple answers!
What I have tried:
I have tried deleting the answer after storing it in one of the buttons so that it couldn't be chosen again but it ended up causing a crash since I was trying to delete a object in the array while using fast enumeration (for loop).
I have tried just detecting if the button title was equal to to the answer after setting the correct answer to a specific button but that didn't work for some odd reason (no crash). There will still multiple buttons with the same answer
What I need help with: How should I stop the answer from being in multiple buttons so that the quiz isn't showing the obvious answer?
What should I do instead?
Thanks!
Edit1: So I pretty much made a NSArray of my four UIButtons.
I put the answer into a random UIButton like this:
NSInteger chosen = (arc4random() % 4);
UIButton *randButton = (UIButton *)[buttonArray objectAtIndex:chosen];
[randButton setTitle:imageName forState:UIControlStateNormal];
Then I title the other buttons like so, my buttons that do not have the answer have a title of nothing so I do this:
- (void)titleButtons {
for (UIButton *buttons in buttonArray) {
if ([[buttons titleForState:UIControlStateNormal] == nil]) {
UIButton *button = buttons;
NSString *superheroString = (NSString*)[superheroArray objectAtIndex:(arc4random() % [superheroArray count])];
[button setTitle:superheroString forState:UIControlStateNormal];
[self checkTitles:button];
}
}
Then the checkTitle method looks like this, this is the method where I try to make sure where 2 buttons do not have the same answer as the imageName (answer):
- (void)checkTitles:(UIButton*)button {
if ([[button titleForState:UIControlStateNormal] isEqualToString:imageName]) {
//Duplicate Answer so re-title button
NSString *newTitle = [superheroArray objectAtIndex:(arc4random() % [superheroArray count])];
[button setTitle:newTitle forState:UIControlStateNormal];
//Call same method again to see if new title is still same answer as pic to avoid same answers
[self checkTitles:button];
}
}
}
If you have an NSArray with all your answers, and you want 1 correct answer and 3 different wrong answers, you can do the following:
Decide in which button do you want the right answer. (randomize it)
Get a random answer from your array and store the index of that answer in a temporary array.
Get another random answer and make sure you are not picking an answer with the same index as the one you have in your temp array, (and again, store the new index in the temporary array)
Don't compare strings using ==. This compares pointer addresses. Use isEqualToString: instead:
if (stringA == stringB)
Usually won't work (will for some constant strings)
if ([stringA isEqualToString:stringB])
Will always work.

Change background image of a button without extra buttons

I've set a button with an image as it's background, and I'm trying to get the image to change back and forth from 2 different images when pressed.
For example, a happy face when pressed would switch to a sad face, and when pressed again would switch back to a happy face and so on.
Any help you can offer would be amazing before I pull anymore hair out.
set the images for two different states: normal and selected,
have the button target an action that toggles the selected state on the button/sender
UIButton* myButton;
- (IBAction)buttonPressed {
if(alreadySelected) {
myButton.imageView.image = myNormalImage;
} else {
myButton.imageView.image = mySelectedImage;
}
}
Not sure, but I think this should do it.
What BoopMeister said, except as bshirley pointed out, you need this API call:
[myButton setImage:happyImage forState:UIControlStateNormal];

Resources