Trying to get the amount of time selected by a user from a UIDatePicker set to mode:"UIDatePickerModeCountDownTimer" in InterFace Builder. Some other stacks say to just check the value of the property countDownDuration on the object.
#property (weak, nonatomic) IBOutlet UIDatePicker *hereIsThePicker;
...
NSLog(#"%f", self.hereIsThePicker.countDownDuration);
But this value often reports a range of values, I've seen numbers such as 70, 80, 113, etc for a selection of "0 Hours, 0 Minutes". So apparently countDownDuration is not what I need.
Does anyone have any hints or clues on how to use UIDatePickerModeCountDownTimer and convert the selection to number of seconds selected? so 1 Minute Selected = 60 Seconds, or 1 Hour 5 Minutes Selected = 3900 seconds ?
Been trying to track this down for 2 days now and just can't seem to get my head around what is going on.
Here is a screenshot of an example application that I setup that just has these two components. You can see the IBOutlet, and a button with an IBAction that is fetching the time and NSLogging it to the bottom of the screen:
Finally after trying random stuff for days, the simple answer, for whatever reason is you need to set a value to countDownDuration, even if you don't need to:
[self.timerPicker setCountDownDuration:60.0f]; //Defaults to 1 minute
In your header .h file put this
#interface ViewController : UIViewController
{
__weak IBOutlet UIPickerView *datePick;
NSMutableArray *hoursArray;
NSMutableArray *minsArray;
NSTimeInterval interval;
}
- (IBAction)calculateTimeFromPicker:(id)sender;
in your .m file put this
- (void)viewDidLoad
{
[super viewDidLoad];
//initialize arrays
hoursArray = [[NSMutableArray alloc] init];
minsArray = [[NSMutableArray alloc] init];
NSString *strVal = [[NSString alloc] init];
for(int i=0; i<61; i++)
{
strVal = [NSString stringWithFormat:#"%d", i];
//NSLog(#"strVal: %#", strVal);
//Create array with 0-12 hours
if (i < 13)
{
[hoursArray addObject:strVal];
}
//create arrays with 0-60 mins
[minsArray addObject:strVal];
}
NSLog(#"[hoursArray count]: %d", [hoursArray count]);
NSLog(#"[minsArray count]: %d", [minsArray count]);
}
//Method to define how many columns/dials to show
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// Method to define the numberOfRows in a component using the array.
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent :(NSInteger)component
{
if (component==0)
{
return [hoursArray count];
}
else
{
return [minsArray count];
}
}
// Method to show the title of row for a component.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
switch (component)
{
case 0:
return [hoursArray objectAtIndex:row];
break;
case 1:
return [minsArray objectAtIndex:row];
break;
}
return nil;
}
- (IBAction)calculateTimeFromPicker:(id)sender
{
NSString *hoursStr = [NSString stringWithFormat:#"%#",[hoursArray objectAtIndex:[pickerView selectedRowInComponent:0]]];
NSString *minsStr = [NSString stringWithFormat:#"%#",[minsArray objectAtIndex:[pickerView selectedRowInComponent:1]]];
int hoursInt = [hoursStr intValue];
int minsInt = [minsStr intValue];
interval = 0 + (minsInt*60) + (hoursInt*3600);
NSString *totalTimeStr = [NSString stringWithFormat:#"%f",interval];
}
Related
I have a program where a user enter strings into an NSMutableArray (myArray) via a Text Field. This array is passed into the next view controller where there is a label (myLabel) and two buttons. Printed to the label is a random string from myArray. ButtonA displays a different random string from the array when pressed and ButtonB removes the current string that is printed to the label and then displays a random string from the array to the label.
This is my current solution:
- (void)viewDidLoad {
self.myLabel.text = [self.myArray objectAtIndex:arc4random() % [myArray count]];
-(IBAction)ButtonA:(id)sender {
self.myLabel.text = [self.myArray objectAtIndex:arc4random() % [myArray count]];
}
-(IBAction)ButtonB:(id)sender {
NSInteger index = [myArray indexOfObject: //what goes here?];
[self.myArray removeObjectAtIndex:index];
self.myLabel.text = [self.myArray objectAtIndex:arc4random() % [myArray count]];
}
Is there a way to get the index of the random string displayed and then remove it from the array? I want this to continue doing this until all items from the array have been removed. Thank you
The // what goes here? should simply be self.myLabel.text.
Though it might be better to add an instance variable that saves off the last random index. Then all array index references should be made with that instance variable.
You also have the same line of code to calculate a random number and set a label repeated 3 times. Create a new method for that and call that function from the three places you have it now.
There are two ways you can do this:
The first way is to store the string you got from your random method. You can declare a global variable for this in your class. And I suggest that you always place a block of similar code in another method.
NSString *generatedString;
- (NSString *)generateRandomString
{
generatedString = [self.myArray objectAtIndex:arc4random() % [myArray count]];
return generatedString;
}
Then in your implementation:
- (void)viewDidLoad
{
self.myLabel.text = [self generateRandomString];
}
- (IBAction)buttonA:(id)sender
{
self.myLabel.text = [self generateRandomString];
}
- (IBAction)buttonA:(id)sender
{
[self.myArray removeObject:generatedString];
self.myLabel.text = [self generateRandomString];
}
Another way is to store the index of the string generated:
NSInteger generatedStringIndex;
- (NSString *)generateRandomString
{
generatedStringIndex = arc4random() % [myArray count];
NSString generatedString = [self.myArray objectAtIndex:generatedStringIndex];
return generatedString;
}
Then in your implementation:
- (void)viewDidLoad
{
self.myLabel.text = [self generateRandomString];
}
- (IBAction)buttonA:(id)sender
{
self.myLabel.text = [self generateRandomString];
}
- (IBAction)buttonA:(id)sender
{
[self.myArray removeObject:generatedStringIndex];
self.myLabel.text = [self generateRandomString];
}
I have a UIPickerView array of seconds which i would like to link to an NSTimer.
in quiz.h file
#property (strong, nonatomic) IBOutlet UIPickerView *timePicker;
i have the array in quiz.m file:
- (void)viewDidLoad {
[super viewDidLoad];
self.pickerData = #[#"1 second", #"2 seconds", #"3 seconds", #"4 seconds", #"5 seconds"];
self.timePicker.dataSource = self;
self.timePicker.delegate = self;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
[self.pickerData objectAtIndex:[self.timePicker selectedRowInComponent:0]];
}
and i would like to link this array of seconds to a property in the imageview.h file
#property (nonatomic, assign) int seconds;
how can i do that within the quiz.m file?
i am trying:
ImageViewController *ivc = [[ImageViewController alloc] init];
ivc.seconds = [self.timePicker selectedRowInComponent:0]; // warning displays conversion loses integer precision
what do i add in ivc.seconds to link it to the picker array and get the number seconds in each row when selected?
i want to link the seconds to a NSTimer.
[NSTimer scheduledTimerWithTimeInterval:self.seconds target:self selector:#selector(timeout)
userInfo:nil repeats:NO];
timeout method pops to rootview
make self.pickerData = #[#"1", #"2", #"3", #"4", #"5"]; and in picker methods,
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
int value = [[self.pickerData objectAtIndex:row] intValue];
NSString *secondString = (value > 1) ? #"seconds" : #"second"
NSString *title = [NSString stringWithFormat:#"%# %#", [self.pickerData objectAtIndex:row], secondString];
return title;
}
and on creating
NSInteger row = [self.timePicker selectedRowInComponent:0];
ImageViewController *ivc = [[ImageViewController alloc] init];
ivc.seconds = [[self.pickerData objectAtIndex:row] intValue];
to show the count down timer, set up tim er first
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(setTimeToLabel) userInfo:nil repeats: YES];
then in setTimeToLabel method
-(void) setTimeToLabel
{
if (self.seconds != 0) {
self.timeLabel.text = [NSString stringWithFormat:#"%d", self.seconds];
self.seconds = self.seconds - 1;
} else {
[timer invalidate];
}
}
I have a chunk of string and i am taking all string in array list separate by white space and want to display in same text box one by one suppose i have a string "my name is xyz" then text box should contends data like this "my" then wait for few seconds and then display "name" and again wait and display "is" and so on.....
- (IBAction)btnstart:(id)sender {
NSString *myString=self.textcollector.text;
NSArray *readerArray=[myString componentsSeparatedByString:#" "];
int arraylenght=[readerArray count];
textcollector.text=#"";
for(int i=0;i<arraylenght;i++)
{
//textcollector=NULL;
self.textcollector.text=readerArray[i];
//NSLog(#" ",readerArray[i]);
sleep(1);
// textcollector.a
}
}
See my code :
In your .h file : define array of string.
#property (strong, nonatomic) NSArray *aryAll;
In your .m file .
#synthesize aryAll;
In btnstart
- (IBAction)btnstart:(id)sender {
self.aryAll = [[NSArray alloc] init];
NSString *stringAnimation = #"My name is kirit modi come from deesa city";
aryAll = [stringAnimation componentsSeparatedByString:#" "];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
[self animationString];
});
}
Method for animation :
-(void)animationString
{
for (int i =0; i< aryAll.count; i++)
{
dispatch_async(dispatch_get_main_queue(),
^{
[labnanme setText:[aryAll objectAtIndex:i]];
});
[NSThread sleepForTimeInterval:1];
}
}
You output is:
Try this ,declare readerArray and i as global
NSArray *readerArray;
int i;
- (IBAction)btnstart:(id)sender
{
NSString *myString=self.textcollector.text;
readerArray=[myString componentsSeparatedByString:#" "];
NSUInteger arraylenght=[readerArray count];
self.statuslabel.text=#"";
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(showText) userInfo:nil repeats:YES];
}
-(void)showText
{
if (i<[readerArray count])
{
self.textcollector.text=readerArray[i];
i++;
}
}
invalidate the timer at last
Thanks so much!
I am working on an application that has a tap counter to set a quantity in a label then the label value is multiplied by the quantity set by the tap counter,
the label will reset to 0 , but the tap counter does not, so when user taps on counter it starts from last count
#implementation ViewController
//These are the tap counter buttons .m//
- (IBAction)oneClicker:(UIButton *)sender
{
counter++;
[_fourLabel setText:[NSString stringWithFormat:#"%d", counter]];
}
- (IBAction)oneAClicker:(UIButton *)sender
{
counter--;
[_fourLabel setText:[NSString stringWithFormat:#"%d", counter]];
// these are the calculate & reset buttons in .m //
- (IBAction)calculateButton:(UIButton *)sender
{
double total = ([self.fourLabel.text integerValue] * 4)+ ([self.sixLabel.text integerValue] * 6)+ ([self.ninetyFiveLabel.text integerValue] * 0.95)+ ([self.twoLabel.text integerValue] * 2)+ ([self.twoaLabel.text integerValue] * 2)+ ([self.threeLabel.text integerValue] * 3)+ ([self.oneFiftyLabel.text integerValue] * 1.5);
self.totalLabel.text = [NSString stringWithFormat:#"$%.2f",total];
}
- (IBAction)resetButton:(UIButton *)sender
{
self.fourLabel.text = #"0";
self.sixLabel.text = #"0";
self.ninetyFiveLabel.text = #"0";
self.twoaLabel.text = #"0";
self.twoLabel.text = #"0";
self.threeLabel.text = #"0";
self.oneFiftyLabel.text = #"0";
self.totalLabel.text = #"$0";
// self.fourLabel.text = #"";
}
// this is .h i will just show a few //
#interface ViewController : UIViewController
{
NSInteger counter;
}
#property (strong, nonatomic) IBOutlet UILabel *fourLabel;
- (IBAction)calculateButton:(UIButton *)sender;
- (IBAction)resetButton:(UIButton *)sender;
counter = 0;
This assumes that counter is an integer. If its something else, just adjust accordingly.
Building a custom UIPickerView for so I can let my users select time as 24 hours without having to go into the Settings app and turn on 24 hour time for the entire phone. Got some stubborn leaks of a couple strings and an array, and I could really use some help.
There are only three places where the arrays I'm creating with the strings are used. hours and minutes are both NSArray synthesized properties as well as ivars.
a) In viewWillAppear:animated, where the strings and arrays are actually created:
if (TwentyFourHourMode) {
//set up arrays for 24 hour picker
NSMutableArray *hoursMutable = [[NSMutableArray alloc] init];
NSString *hourString;
for (int i = 0; i < 24; i++) {
if (i < 10) {
hourString = [NSString stringWithFormat:#"0%i", i];
} else {
hourString = [NSString stringWithFormat:#"%i", i];
}
[hoursMutable addObject:hourString];
}
self.hours = [[NSArray alloc] initWithArray:hoursMutable];
[hoursMutable release];
NSMutableArray *minutesMutable = [[NSMutableArray alloc] init];
NSString *minuteString;
for (int i = 0; i < 60; i++) {
if (i < 10) {
minuteString = [NSString stringWithFormat:#"0%i", i];
} else {
minuteString= [NSString stringWithFormat:#"%i", i];
}
[minutesMutable addObject:minuteString];
}
self.minutes = [[NSArray alloc] initWithArray:minutesMutable];
[minutesMutable release];
//more stuff which does not leak or reference the arrays/strings in question
} else {
//unrelated crap
}
b) in my UIPickerView delegate methods - everything that uses these two arrays:
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (component == 0) {
return self.hours.count;
} else if (component == 1) {
return self.minutes.count;
} else {
return 0;
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (component == 0) {
return [self.hours objectAtIndex:row];
} else if (component == 1) {
return [self.minutes objectAtIndex:row];
} else {
return nil;
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
switch(component) {
case 0: return 44;
case 1: return 50;
default: return 44;
}
}
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (component == 0) {
[hour24 release];
hour24 = [self.hours objectAtIndex:row];
[hour24 retain];
} else if (component == 1) {
[minute24 release];
minute24 = [self.minutes objectAtIndex:row];
[minute24 retain];
}
c) and last but not least, in dealloc:
//set arrays to nil
self.hours = nil;
self.minutes = nil;
//release arrays
[hours release];
[minutes release];
Analyze is coming up clean, but Instruments is telling me hourString, minuteString, and self.hours are all being leaked. What really drives me nuts is that self.minutes isn't being leaked and it appears to be the same format of code as self.hours - I even copy-pasted and still get the same leak/no leak combo.
I'll be damned if I can figure out where this is coming from. Any ideas? Any further code y'all might need to help? Thanks, guys!
Edit: EmptyStack's suggestion stopped self.hours and minuteString from being leaked, but hourString is still leaking and there's now a new leak in this code just below the stuff above in viewWillAppear:animated (self.incomingTime is a synthesized NSString property, all arrays here are initialized locally):
NSArray *splitStrings = [self.incomingTime componentsSeparatedByString:#":"];
NSString *hourToDisplay = [splitStrings objectAtIndex:0];
//set this here so it doesn't give a null value
hour24 = [[NSString alloc] initWithString:hourToDisplay];
NSString *minuteSplitter = [splitStrings objectAtIndex:1];
NSArray *splitMinutes = [minuteSplitter componentsSeparatedByString:#" "];
NSString *minuteToDisplay = [splitMinutes objectAtIndex:0];
minute24 = [[NSString alloc] initWithString:minuteToDisplay];
Edit 2: Oh, for crying out loud, now minuteString is leaking again. I'm going to bed before my head explodes. Any suggestions overnight would be most welcome.
The problems are in the following lines,
self.hours = [[NSArray alloc] initWithArray:hoursMutable];
self.minutes = [[NSArray alloc] initWithArray:minutesMutable];
It seems hours and minutes are "retained properties" and you are allocating objects while assigning it to the properties. For example on the first line, [NSArray alloc] increases the retainCount by 1 and the setter self.hours in turn increases the retainCount by 1. Finally the retainCount becomes 2, which causes the leak even after you release those objects. You can use convenience constructors in these cases.
self.hours = [NSArray arrayWithArray:hoursMutable];
self.minutes = [NSArray arrayWithArray:minutesMutable];
And even a simpler way is to directly assign those arrays like this,
self.hours = hoursMutable;
self.minutes = minutesMutable;
Okay, finally found it, for anyone stumbling across this in the future: hour24 and minute24 were not being properly released in dealloc, so it was leaking strings and arrays all over the place. I found it by commenting out the code posted in the 2nd edit and putting it back in line by line until the leak sprang up. Thanks for the suggestions!