I am getting millisecond and i want to convert that millisecond to day,hours,minutes,second and display and want to display it in uiTableview. and i want to update that timer every second..
i had try this code using uiTableview delegate method cellForRowAtIndexPath.
NSInteger totleTime = [[[productListDataArray objectAtIndex:indexPath.row]objectForKey:#"_auction_duration"] integerValue];
totleTime = totleTime - timerValue ;
long days = (totleTime) / (60 * 60 * 24);
long hours = (totleTime - days * 60 * 60 * 24) / (60 * 60);
long minuts = (totleTime - days * 60 * 60 * 24 - hours * 60 * 60) / 60;
long seconds = (totleTime - days * 60 * 60 * 24 - hours * 60 *60 - minuts * 60);
NSLog(#"seconds : %.f minutes : %.f hours : %.f days : %.f ", seconds, minuts, hours, days);
I had used this method for call method and update tableview. but its not working so suggest me another option or tell me what i had done wrong in this code..
What I understand from your question is that you want to reload your tableView every second. First of all, let me say that it is a bad idea. If your tableView is being reloaded then the user will not be able to see anything. Having said that, you can use a timer with a certain interval that calls a method. That method can decide when to reload the tableView.
EDIT
From your last comment, I understand that you are trying to display a countdown timer in a tableview cell. For that purpose, you don't need to reload the tableview. You only have to update the datasource and reload the row that is displaying the counter. Something along these lines.
The code snippet below is in Swift 2
//Call a method named tick() every second
let timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
func tick() {
//DO YOUR CALCULATIONS HERE TO CALCULATE YOUR DAYS, MINUTES, etc. THEN CALL THE FOLLOWING METHOD
tblView.reloadRowsAtIndexPaths([NSIndexPath(forRow: {rowNumber}, inSection: {sectionNumber})], withRowAnimation: .None)
//ALSO MAKE SURE YOUR cellForRowAtIndexPath IS CORRECTLY SETTING THE CELL VALUES
}
Don't forget to invalidate the timer when you're finished with it
i have get solve this issues.
1.At initial i had set timer is 1 second.
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
2.Every Second Call Method and change value and reload tableview.
- (void)updateCounter:(NSTimer *)theTimer {
timerValue += 1;
[ProductListTableView reloadData];
}
3. now calculate remaining time in uitableView deleget method cellForRowAtIndexPath
NSInteger totleTime = [[[productListDataArray objectAtIndex:indexPath.row]objectForKey:#"_auction_duration"] integerValue];
totleTime = totleTime - timerValue ;
long days = (totleTime) / (60 * 60 * 24);
long hours = (totleTime - (days * 60 * 60 * 24)) / (60 * 60) ;
long minuts = (totleTime - (days * 60 * 60 * 24) - (hours * 60 * 60)) / 60;
long seconds = (totleTime - (days * 60 * 60 * 24) - (hours * 60 * 60) - (minuts * 60));
cell.saleTimeLabel.text = [NSString stringWithFormat:#"%# Sold %ld:%ld:%ld:%ld",[[productListDataArray objectAtIndex:indexPath.row]objectForKey:#"sales_qty"], days,hours,minuts,seconds];
I don't know timeValue's meanings, if timeValue assume system time. you can write a timer to reload tableView's data.
Related
I'm optimizing the scrolling smoothness of a UITableView, but it's tough to notice subtle gains by eye. I'm looking for a straightforward way to print out the "load time" of each UITableViewCell as it appears. Is this possible?
but it's tough to notice subtle gains by eye.
Don't try. Use Instruments! That's what it's for. The Core Animation instrument will tell you the FPS when you scroll, which is exactly what you want to know here. And the Time Profiling instrument will tell you exactly where in your code the time is being spent.
Don't guess. Don't eyeball. Don't add your own timing instrumentation. Use Instruments!
You can do two things:
1: Measure execution time for - tableView:cellForRowAtIndexPath:
2: Measure execution time for - reloadData
Measuring:
- (UITableViewCell * _Nonnull)tableView:(UITableView * _Nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * _Nonnull)indexPath {
CFTimeInterval startTime = CACurrentMediaTime();
//Do your thing - dequeue, setup your cell.
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(#"Cell Creation: %g s", endTime - startTime);
return cell;
}
and wherever you call reloadData()
CFTimeInterval startTime = CACurrentMediaTime();
[self.tableView reloadData];
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(#"Cell Creation: %g s", endTime - startTime);
you can use the mach absolute time for the most accurate results. there is a good explanation here: https://developer.apple.com/library/mac/qa/qa1398/_index.html
example code:
uint64_t startTime = mach_absolute_time();
// do work here
uint64_t endTime = mach_absolute_time();
uint64_t elapsedTime = endTime - startTime;
mach_timebase_info_data_t sTimebaseInfo;
mach_timebase_info(&sTimebaseInfo);
uint32_t numer = sTimebaseInfo.numer;
uint32_t denom = sTimebaseInfo.denom;
uint64_t elapsedNano = (elapsedTime * numer / denom);
NSTimeInterval elapsedSeconds = elapsedNano / (CGFloat)NSEC_PER_SEC;
NSLog(#"elapsed time: %f", elapsedSeconds);
I am trying to pan and seek forwards and backwards in my AVPlayer. It is kind of working but the basic math of determining where the pan is translated to the length of the asset is wrong. Can any one offer assistance?
- (void) handlePanGesture:(UIPanGestureRecognizer*)pan{
CGPoint translate = [pan translationInView:self.view];
CGFloat xCoord = translate.x;
double diff = (xCoord);
//NSLog(#"%F",diff);
CMTime duration = self.avPlayer.currentItem.asset.duration;
float seconds = CMTimeGetSeconds(duration);
NSLog(#"duration: %.2f", seconds);
CGFloat gh = 0;
if (diff>=0) {
//If the difference is positive
NSLog(#"%f",diff);
gh = diff;
} else {
//If the difference is negative
NSLog(#"%f",diff*-1);
gh = diff*-1;
}
float minValue = 0;
float maxValue = 1024;
float value = gh;
double time = seconds * (value - minValue) / (maxValue - minValue);
[_avPlayer seekToTime:CMTimeMakeWithSeconds(time, 10) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
//[_avPlayer seekToTime:CMTimeMakeWithSeconds(seconds*(Float64)diff , 1024) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
You are not normalizing the touch location and the corresponding time values. Is there a 1:1 relationship between the two? That's not possible.
Take the minimum and maximum touch location values of the pan gesture and the minimum and maximum values of the asset's duration (obviously, from zero to the length of the video), and then apply the following formula to translate the touch location to the seek time:
// Map
#define map(x, in_min, in_max, out_min, out_max) ((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
Here's the code I wrote that uses that formula:
- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateChanged){
CGPoint location = [sender locationInView:self];
float nlx = ((location.x / ((CGRectGetMidX(self.frame) / (self.frame.size.width / 2.0)))) / (self.frame.size.width / 2.0)) - 1.0;
//float nly = ((location.y / ((CGRectGetMidY(self.view.frame) / (self.view.frame.size.width / 2.0)))) / (self.view.frame.size.width / 2.0)) - 1.0;
nlx = nlx * 2.0;
[self.delegate setRate:nlx];
}
}
I culled the label that displays the rate, and the Play icon that appears while you're scrubbing, and which changes sizes depending on how fast or slow you are panning the video. Although you didn't ask for that, if you want it, just ask.
Oh, the "times-two" factor is intended to add an acceleration curve to the pan gesture value sent to the delegate's setRate method. You can use any formula for that, even an actual curve, like pow(nlx, 2.0) or whatever...
If you want to make it more precise and useful you should implement different "levels of sensitivity".
Apple does that with their slider: if you drag away from the slider and then to the sides, that pace at which the video moves changes. The farther your are from the slider the more precise it gets/the less you can reach.
Its simple, I need to make a label in my project that says the current g-force from the accelerometer. I have found some code but I don't know where to put it in my code. I am guessing that I need to put it into a void statement but I am not sure. Please point me in the right direction.
sx = acceleration.x * kFilteringFactor + sx * (1.0 - kFilteringFactor);
sy = acceleration.y * kFilteringFactor + sy * (1.0 - kFilteringFactor);
sz = acceleration.z * kFilteringFactor + sz * (1.0 - kFilteringFactor);
float aValue = sqrt(sx*sx+sy*sy+sz*sz);
[gforcelabel setText:[NSString stringWithFormat:#"%.2f",aValue]];
I wouldn't bother with UIAccelerometerDelegate anymore considering it's unlikely at this point you'll need to maintain compatibility for anything below iOS 5. As linked in the other answer, you'll want to use Core Motion instead, specifically, CMMotionManager, which is available in iOS 5 and up. It's easy enough to use too, all you have to do is create an instance of the motion manager (you can only have one), set it's update interval (optional), and start monitoring the specified motion events.
if (!self.manager) {
self.manager = [CMMotionManager new];
}
if (self.manager.isAccelerometerActive) {
[self.manager stopAccelerometerUpdates];
}
NSOperationQueue *queue = [NSOperationQueue new];
[self.manager setAccelerometerUpdateInterval:1.0 / 30.0]; // 30 Updates Per Second
[self.manager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
NSLog(#"X: %f Y: %f Z: %f",accelerometerData.acceleration.x,accelerometerData.acceleration.y,accelerometerData.acceleration.z);
}];
The code I've provided creates a new operation queue on which to process the accelerometer updates, and if you want to update the UI from within the block, you'll have to move back to the main thread first. If you aren't doing any heavy processing within the block, and just need to update the UI (as it looks like you do), you can simply pass [NSOperationQueue mainQueue], instead of creating a new queue.
It's also worth noting that the motion manager can do more than just monitor acceleration data, it also has update blocks for the magnetometer, gyroscope, and device motion. Info can be found in the documentation
UIAccelerometer was deprecated in iOS 5.0. You should use the Core Motion Library instead.
If we suppose that you are targeting iOS 5.0, the code you've listed above would live in a view controller that implements the UIAccelerometerDelegate Protocol. To be specific, you would define the following protocol method and move your code inside the body of this method:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
I figured out exactly how to do it...
Viewcontroller.h
IBOutlet UILabel *currentg;
IBOutlet UILabel *avgAccelLabel;
float avgAccel;
float currentAccel;
int accelCount;
float accelX;
float accelY;
float accelZ;
UIAccelerometer *accelerometer;
Viewcontroller.m
//Use a basic low-pass filter to only keep the gravity in the accelerometer values
accelX = acceleration.x; //* kFilteringFactor + accelX * (1.0 - kFilteringFactor);
accelY = acceleration.y; //* kFilteringFactor + accelY * (1.0 - kFilteringFactor);
accelZ = acceleration.z; //* kFilteringFactor + accelZ * (1.0 - kFilteringFactor);
//calculate acceleration resultant
float accel = sqrt((ABS(accelX)*ABS(accelX))+(ABS(accelY)*ABS(accelY))+ (ABS(accelZ)*ABS(accelZ)));
//keep track of average accel
avgAccel = ((avgAccel * accelCount) + accel)/(accelCount + 1);
currentAccel = (accel);
accelCount++;
//display avg accel
NSString *avgAccelString = [NSString stringWithFormat:#"%.2f%#", avgAccel, #""];
avgAccelLabel.text = avgAccelString;
NSString *currentAccellString = [NSString stringWithFormat:#"%.2f%#",currentAccel, #"" ];
currentg.text = currentAccellString;
viewdidload
self.accelerometer = [UIAccelerometer sharedAccelerometer];
self.accelerometer.updateInterval = 0.4;
self.accelerometer.delegate = self;
I am having a problem with displaying time on UITableViewCell
unsigned long long seconds = milliseconds/1000;
unsigned long long minutes = seconds/60;
unsigned long long hours = minutes/60;
seconds -= minutes * 60;
minutes -= hours * 60;
NSString * result1 = [NSString `enter code here`stringWithFormat:#"%02lluH:%02lluM:%02lluS",hours,minutes,seconds];
self.menushowTime.text = result1;//populate cell label with time
Whenever I am reloading the table view my timer is running with 2x speed, I mean very fast. How can I prevent this from happening.
facing problem when i start scrolling tableview or reloading the tableview.?
Yes it happens, because timer is attached to NSRunLoop, so when the UI thread is busy doing animations , NSRunLoop has to halt. It finishes animations and later increments your timer. so the timer wont increase perfectly during this time.
use below one,
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
first calculate minutes, later seconds.
Change your code to below.
minutes -= hours * 60;
seconds -= minutes * 60;
I want my app to be able to count the number of taps every second. I assume this would have something to do with touchesBegan:..., but that doesn't work on a button, does it? Anyway, how would I measure the number of taps per second?
I think I could do it manually using a counter which resets every second but I was wondering if there is a better way.
Would it add the values to an array? And if so, would I be able to calculate an average excluding 0's?
My current code.
-(void) timer:(NSTimer *)averageTimer {
if(tapCountInLastSecond != 0) {
secondsElapsed++;
averageTapsPerSecond += tapCountInLastSecond / secondsElapsed;
tapCountInLastSecond = 0;
NSLog(#"Average: %f", averageTapsPerSecond);
}
}
in your viewController put those counters
int tapCountInPastSecond = 0;
float averageTapsPerSecond = 0;
int secondsElapsed = 0;
Then add this method that invokes when you the screen or tap a button
- (void)incrementTapCount
{
tapCountInPastSecond++;
}
Create a timer that will fire every second, doing it's calculations, then resets the tap count
- (void)timerActions
{
secondsElapsed++;
averageTapsPerSecond = (averageTapsPerSecond*(secondsElapsed-1) +tapCountInPastSecond) / secondsElapsed;
tapCountInpastSecond = 0;
}
Now you can init your timer like that:
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerActions) userInfo:Nil repeats:YES];
Then at any point you'll be able to get the average Taps/Second by reading the value averageTapsPerSecond
Hope this make sense to you