Cycling through Image Array within Object in Time Intervals (Objective-C) - objective-c

My general question is how do you have an object with an image array:
#import <Foundation/Foundation.h>
#interface Object: NSObject {
UIImage *image[imageNumber];
}
And then take these images and apply them to a button in a different class, starting with imageArray[0] and every few seconds changing it to imageArray[1], etc, but stopping the loop at the last image.
What I specifically did was create a Plant object:
#import <Foundation/Foundation.h>
#interface Plant : NSObject {
UIImage *plantImage[3];
int imageNumber; //to specify which image to display, increments with timer
NSTimer *plantImageTimer;
}
and declared then made a few methods like
-(void)addPlantImages:(UIImage *) firstImage withPlantImage2:(UIImage *) secondImage withPlantImage3:(UIImage *) thirdImage{
plantImage[0] = firstImage;
plantImage[1] = secondImage;
plantImage[2] = thirdImage;
}
//this makes the Plant into a button
-(void)createPlantButtonForPlant:(Plant *) plantType forView:(UIView *) view withButtonRect:(CGRect) buttonRect{
imageNumber=0;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = buttonRect;
button.hidden = NO;
[view addSubview:button];
[plantType growPlant:button]; //explained in code below
}
And from here I don't know what to do anymore.
I tried using an NSTimer, but you can't put parameters into the selector, so I can't specify which button (or Plant) I want to cycle images through.
Extra tidbits of code in Plant that I have (which do not work); I'm using NSTimer userinfo incorrectly, but I don't understand how to use it, to be honest.
-(void)growPlant:(UIButton *) button{
plantImageTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(changePlantImage:) userInfo:button repeats:YES];
}
-(void)changePlantImage: (UIButton *) plantButton{
if(imageNumber == 3){
[plantImageTimer invalidate];
} else {
[plantButton setImage:plantImage[imageNumber] forState:UIControlStateNormal];
imageNumber++;
}
}
I imported Plant into my view controller (called PracticeViewController) and tried to make it so that when I clicked a button, a Plant button popped up and cycled through the images.
(void)buttonAction{
theButton.hidden = YES; //I did make this button, just didn't add the code here. Declared in header.
CGRect imageViewRect = CGRectMake(100, 100, 100, 100);
Plant *testPlant = [Plant new];
[testPlant addPlantImages:[UIImage imageNamed:#"plant2.png"] withPlantImage2:[UIImage imageNamed:#"plant2.png"] withPlantImage3:[UIImage imageNamed:#"plant2.png"];
[testPlant createButtonForPlant:testPlant forView:self.view withButtonRect:imageViewRect];
}
If you need more code or other information, just comment below and I will reply asap.

Now that I've done more programming, I realize how complicated I made this code lol. Anyway, all I would have had to do was add
[button addTarget:self action:#selector(changePlantImage) forControlEvents:UIControlEventTouchUpInside];
after making the button instance. This would then scroll through whichever images the plant had in its array.

Related

Show touch when clicked UIButton Objective-C

I have a UIButton that has only an UIImage set, when Clicked (long press) the images changes automatically with a shadow, What I want is that even if the button gets clicked but not with a long press the images should have the shadow. I already tried from IB to set the UIButton properties Reverse on Highlight and Shows Touch On Highlight but with no results
This is about UIControl Class. It's default to be with shadow. So if you wanna customize it, you should addTarget to your button to every action on UIButton like tapping,long press,touchUpInside and I think it s not about long press it's just you can't realize the difference on tapping.
in one of my project I customize my button actions like this:
buyButton = [[UIButton alloc] initWithFrame:CGRectMake(self.frame.size.width*3/4-2, 0, self.frame.size.width/4+4, self.frame.size.height)];
[buyButton addTarget:self action:#selector(buyButtonClicked:) forControlEvents:UIControlEventTouchDown];
[buyButton addTarget:self action:#selector(buyButtonNormal:) forControlEvents:UIControlEventTouchUpInside];
[buyButton addTarget:self action:#selector(buyButtonNormal:) forControlEvents:UIControlEventTouchUpOutside];
and methods of this like:
- (void) buyButtonClicked:(UIButton *) sender {
if ([self.backgroundColor isEqual:[Util UIColorForHexColor:#"fede32"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"fdca2e"];
}
else if([self.backgroundColor isEqual:[Util UIColorForHexColor:#"cfd3dc"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"c0c5d0"];
}
}
- (void) buyButtonNormal:(UIButton *) sender {
if ([self.backgroundColor isEqual:[Util UIColorForHexColor:#"fdca2e"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"fede32"];
}
else if([self.backgroundColor isEqual:[Util UIColorForHexColor:#"c0c5d0"]]) {
self.backgroundColor = [Util UIColorForHexColor:#"cfd3dc"];
}
[delegate purchaseOffer:selectedOffer];
}
If you need more information about UIButton actions there are a lot of question on this site.

Objective-C, Displaying an NSTimer activated by a UIButton

I'm working on a project for school that includes a set of buttons that create NStimers used as a countdown timer. Ideally, the time would display as the title of the UIButton that started the timer.
So far I have only been able make this work if when setting the display of the time I refer to a specific instance of a UIButton rather than a somehow passing a UIButton argument.
I also have declared "time" NSString that holds the current displayed value calculated by the NSTimer. This is not how the final implementation should be, and I only have it set up like this just to have it partially working.
Code for one of the buttons:
b1 = [[UIButton alloc]
initWithFrame:CGRectMake(neutral.frame.size.width * 0.56, neutral.frame.size.height * 0.18, neutral.frame.size.height * 0.64, neutral.frame.size.height * 0.64)];
[b1.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:35.0]];
[b1 setBackgroundImage: forState:UIControlStateNormal];
Method called from button press action:
-(void)buttonClicked:(id)sender
{
//do stuff
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFired) userInfo:[NSNumber numberWithInt:t] repeats:YES]; }
NSTimer timer fired method:
-(void)timerFired
{
if((curMin>0 || curSec>=0) && curMin>=0)
{
if(curSec==0)
{
curMin-=1;
curSec=59;
}
else if(curSec>0)
{
curSec-=1;
}
if(curMin>-1)
{
time = [NSString stringWithFormat: #"%d%#%02d",curMin,#":",curSec];
[b1 setTitle:time forState:UIControlStateNormal];
}
}
else
{
[b1 setTitle: nil forState:UIControlStateNormal];
[timer invalidate];
}
}
I hope that was clear enough as to what I am trying to accomplish. I am somewhat surprised that I haven't been able to find anything to walk me through this. I am flexible to changing how exactly this works. All that really matters is that each button can start a unique countdown timer.
I'm sure that this code is sloppy, but Objective C is relatively new to me so any help at all would be appreciated.
Don't store time as minutes/seconds, just use seconds, as all that greater than 60 logic is really tedious isn't it.
I've chosen to call the instance variable _secondsLeft so I will know what it means when I look at the code in 6 months time:
-(void)timerFired
{
NSString *formatted = #"";
if (secondsLeft > 0)
{
secondsLeft--;
formatted = [NSString stringWithFormat:#"%d:%02d", (secondsLeft / 60), (secondsLeft % 60)];
} else {
[timer invalidate];
}
[b1 setTitle:formatted forState:UIControlStateNormal];
}

iOS take user input and have it stored as a global variable [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to make a test Application that when a user clicks a button, the text is toggled to something else and if its clicked again, it goes back but I also want to be able to add a section in which the user enters his/her names so it says , the hidden message was: or whatever...
The code I have is:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//button.backgroundColor = [UIColor redColor];
button.titleLabel.textColor=[UIColor blackColor];
button.frame = CGRectMake(25, 100, 275, 60);
[button setTitle:#"Press this button to reveal the text!" forState:UIControlStateNormal];
[button addTarget:self action:#selector(button_method:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)button_method:(UIButton *)button {
NSString *test = #"I am learning Objective-C for the very first time! Also, this is my first ever variable!";
// handle button press
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(25, 25, 275, 60)];
label.text = test;
label.numberOfLines = 0;
label.lineBreakMode = UILineBreakModeWordWrap;
//label.lineBreakMode = NSLineBreakByWordWrapping; //iOS 6 only
[self.view addSubview:label];
[button setTitle:#"You have pressed the button!" forState:UIControlStateNormal];
[button addTarget:self action:#selector(change_again:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)change_again:(UIButton *)button {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(25, 25, 275, 60)];
label.text = #"You have found the next piece of text!";
label.numberOfLines = 0;
label.lineBreakMode = UILineBreakModeWordWrap;
//label.lineBreakMode = NSLineBreakByWordWrapping; //iOS 6 only
[self.view addSubview:label];
[button setTitle:#"Keep pressing!" forState:UIControlStateNormal];
[button addTarget:self action:#selector(button_method:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
I hope this isn't considered to be too localized!
muqman
PS: A side question, how would I create a string such as NSString *var4 = var.var2.var3;
what is the joining character? In JavaScript it's + in PHP it's .
You probably want to use a #property to store the text input. Properties are like instance variables but they introduce another layer of abstraction by adding getters and setters retrieved whenever the ivars are retrieved (get) or assigned (set). At the moment all your variables only exist within your methods. A property will allow those variables to be accessed from different methods. Here's a crash course:
A property is declared in the #interface section (use the header file for properties accessible from other classes, use the main file for properties accessible only from your class).
#property (strong, nonatomic) NSString *userInput;
In the #implementation section must write your own getter and setter or you can automatically create your getters and setters using synthesize:
#synthesize userInput = _userInput;
From here you're able to use the property.
//Assigning the property
self.userInput = #"Some text";
//Retrieving the property
label.text = self.userInput;
I you want to learn all about properties, here's Apple's documentation.
One last thing about properties: Since they are instance variables, they are tied to the instance of the class and hence they won't persist between launches of your program.
For text input, try a UITextField.
If you're just starting programming iOS, I'd recommend Stanford's CS193p on iTunes U. I'm pretty sure he uses a custom getter and goes through the reasons you would want to write one when he writes a calculator app in lecture 2.
There are two ways of using global variables. First, you can set a global variable (only available within that class and during the current session) in the Interface section of either your header or implementation method. Here's an example:
// ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
NSString *nameOfGlobalVariable;
}
#end
OR, in iOS you can store defaults with a storage system called NSUserDefaults. NSUserDefaults allow you to set and access defaults at any time, in any class, and during any app session. The defaults are stored in a PLIST file inside of your app's bundle. Here's how to set a default:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"YourText" forKey:#"NameOfDefault"];
[defaults synchronize];
You can also explore the NSUserDefaults method and try changing out setObject for something like setBool. Retrieving a default is very similar- simply define the NSUserDefaults, and use the [objectForKey] method to retrieve it. I'll leave you to figure that part out, because programing isn't fun when you just copy and paste ;)
Good luck!
Just try something like that:-
// In .h file, define your enum...
enum
{
MDefaultButtonText = 1,
MToggleButtonText
};
// In .m file, define your string if the text not changed...
#ifndef MDefaultButtonTextString
#define MDefaultButtonTextString "This is default string"
#endif
#ifndef MToggleButtonTextString
#define MToggleButtonTextString "This is toggled string"
#endif
/*
Please note, you can also used:-
const NSString *testStr = #"your required string";
// Feel free if you think to know more...
*/
Now, in viewDidLoad:-
[yourButton setTag:1];
[yourButton addTarget:self action:#selector(someProcedure:) forControlEvents:UIControlEventTouchUpInside];
Now, you do need of implementing your click event...
-(void)someProcedure:(id)sender
{
// Do your stuff here...
switch([sender tag])
{
case MDefaultButtonText://sender.tag = 1
[sender setTag:2];
[sender setTitle:MToggleButtonTextString forState:UIControlStateNormal];
// In alert set Message to = MDefaultButtonTextString
break;
case MToggleButtonText:////sender.tag = 2
[sender setTag:1];
[sender setTitle:MDefaultButtonTextString forState:UIControlStateNormal];
// In alert set Message to = MToggleButtonTextString
break;
default:
//if you required...
break;
}
}
Please cross check the required message accordingly to your requirement.Hope, it'll sort your issue.
Any concern, just get back to me. :)

Specific action for each buttons in UIScrollView

I have an UIScrollView page . On this UIscrollView I have different images inside buttons you can see it in below code, and I want to load this images in UIWebView when I press the buttons, My question is how can I know which button are click. Would you please give me some hint for implementing this?
I'm new to objective-C
Here is my action: I want to have one action for each images, rightnow I have just one action for all images, I one to have one for each image
- (IBAction)openAction:(id)sender {
NSLog(#"test");
}
The actual button is passed to the IBAction. Setting a tag on the button is one way of doing it. If you created outlets for all your buttons in Interface Builder, you can simply do something like this:
- (IBAction)openAction:(id)sender {
UIButton *b = (UIButton *)sender;
if ([b isEqual:self.outletButton1]) {
// Do something with button 1
}
else if ([b isEqual:self.outletButton2]) {
// Do something with button 2
}
}
Don't use Same Tag for Button. Use Different Tag for different button.
For ex [btn setTag:1] .
you can use [btn setTag:i];
Dynamic value
Give each button a unique tag, in your code or in Interface Builder.
Then in your action you can do:
- (IBAction)openAction:(id)sender {
UIButton *b = (UIButton *)sender;
NSLog(#"button %d is pressed", b.tag);
}
I see that you already give your imageviews tags. Those are not buttons! You should instead create UIButtons whose content are images. See UIButton's setImage:forState:
Edit: In response to your question below, here's an example:
NSMutableArray *bArray = [NSMutableArray arrayWithCapacity:kNumImages];
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn setImage:imageName forState:UIControlStateNormal];
btn.tag = 100+i;
[bArray addObject:btn];
}
You don't have to add UIButton over UIImageView. Instead, you can set the image for UIButton like this.
[btn setImage:[UIImage imageNamed:#"image1"] forState:UIControlStateNormal];
You can access the image in the action like this:
- (IBAction)openAction:(id)sender {
if([[btn currentImage] isEqual:[UIImage imageNamed:#"image1"]]){
}
NSLog(#"test");
}

How to have a UIKit button open another view?

I have a grid of buttons in one page. I want the buttons to lead to another view when clicked. What should I add to the following action to change the view?
-(void)buttonPressed:(UIButton *)button {
NSLog(#"button %u -- frame: %#", button.tag, NSStringFromCGRect(button.frame));
}
The grid of buttons is created with:
{
int rows = 13, columns = 4;
UIView *buttonView = [[UIView alloc] initWithFrame:CGRectMake(0.f, 0.f, 80*columns, 32*rows)];
int currentTag = 0;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < columns; x++) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
// [button.layer setBorderWidth:1.0];
// [button.layer setBorderColor:UIColor blackColor]];
button.backgroundColor=[UIColor colorWithRed: 201.0/255.0 green: 201.0/255.0 blue:201.0/255.0 alpha: 1.0];
button.tag = currentTag;
currentTag++;
[button.layer setBorderColor: [[UIColor blackColor] CGColor]];
[button.layer setBorderWidth: 1.0];
[button setTitle:[NSString stringWithFormat:#"%d",currentTag] forState:UIControlStateNormal];
button.frame = CGRectMake(80*x, 32*y, 80, 32);
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonView addSubview: button];
}
}
// Center the view which contains your buttons
CGPoint centerPoint = buttonView.center;
centerPoint.x = self.view.center.x;
buttonView.center = centerPoint;
[self.view addSubview:buttonView];
}
Maybe you want to connect an action?
[button addTarget:self
selector:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
(check syntax, this is by memory...)
Rinju's answer would work, but it needs a little more explanation. I'm not sure why exactly you would like to create this grid of buttons (more info would be nice), but if you want each button to show a new view, then tags are important!
If you want to open the same view, but with different properties shown on that view, you'd need to create a new view controller class. Let's call this DetailViewController.
Now, in your buttonPressed: method, you're going to need to instantiate this view controller and set a property of it!
#interface DetailViewController : UIViewController
#property (nonatomic, assign) int buttonTag;
...
//other methods, properties, etc. here
...
#end
Now, in your view controller where the buttons are, you can do this (for the sake of simplicity, I will assume you are using storyboards. If not, it can still be easily accomplished similar to what Rinju has done).
-(void)buttonPressed:(UIButton*)button {
[self performSegueWithIdentifier:#"DetailView" sender:button];
}
Now, you can implement the prepareForSegue method, which is called just before the segue fires:
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender {
if( [[segue identifier] isEqualToString:#"DetailView"] ) {
DetailViewController *detailView = [segue destinationViewController];
detailView.buttonTag = ((UIButton*)sender).tag;
}
}
Now that the tag is set for your new detail view controller, you can probably use switch statements (or better yet, a model object which is passed this buttonTag) in viewDidLoad: of the DetailViewController to set up the UI there. Basically what we are doing is using the tag of the button to distinguish which button was pressed, and based on this create a new view!
What you may want to do is create a typedef enum structure to make names for the tags instead of using raw integers. This will increase the readability of your code, and also will help you in not getting confused ;)
-(void)buttonPressed:(UIButton *)button
{
NSLog(#"button %u -- frame: %#", button.tag, NSStringFromCGRect(button.frame));
Cart *crtObj=[[Cart alloc]initWithNibName:#"Cart" bundle:nil];
[self.navigationController pushViewController:crtObj animated:YES];
[crtObj release];
}