简体   繁体   English

UIScrollView滚动不流畅?

[英]UIScrollView does not scroll smooth?

I have a IPhone app that has 10 NSTimer functions that check every .5 second on a view that scrolls. 我有一个iPhone应用程序,它有10个NSTimer函数,可以在滚动的视图上每隔0.5秒检查一次。 Each timer has 3 labels, 1 text field and 1 UIImageView . 每个计时器有3个标签,1个文本字段和1个UIImageView All 30 labels, 10 text fields and 10 UIImageViews need to scroll. 需要滚动所有30个标签,10个文本字段和10个UIImageViews
Problem 1 is the view does not scroll smooth. 问题1是视图不滚动平滑。 I have seen some suggestions on here and have tried then with no success. 我在这里看到了一些建议,然后尝试了没有成功。 When you start to scroll, it takes a split second to start, then it jumps about 150 pixels then it starts scrolling. 当你开始滚动时,它需要一瞬间开始,然后它跳跃大约150个像素然后它开始滚动。
Problem 2 is that when it is scrolling, the text fields and labels are not being updated by the NSTimer.. When you stop scrolling the fields jump to the correct time. 问题2是滚动时,NSTimer不会更新文本字段和标签。当您停止滚动时,字段会跳转到正确的时间。 is this just to much for the iPhone to handle or is there something I am missing? 这对于iPhone来说还是要处理的还是我缺少的东西?

I added some of my "rude" code. 我添加了一些“粗鲁”的代码。 This is just one NSTimer that is checking every 0.5 seconds. 这只是一个每0.5秒检查一次的NSTimer。 I also have all my pointers releasing and set to nil in the viewDidUnload. 我也发布了所有指针,并在viewDidUnload中设置为nil。 The dates are different where they will have holiday info and possible more info added in the array at a later date. 日期是不同的,他们将有假日信息,并在以后的数组中添加更多信息。

Update:I have ran this app on my iPhone 4 and it is NOT smooth. 更新:我已经在我的iPhone 4上运行了这个应用程序并且它顺畅。 It IS smooth however in the iPhone simulator. 然而,它光滑的iPhone模拟器。

-(void)updateUSDTimer {      

NSMutableArray *usdMarketHours = [[NSMutableArray alloc] init];

[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"2", @"29", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:0];// open WED
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"2", @"29", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:1];// close

[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"1", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:2];// open THU
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"1", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:3];// close
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"2", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:4];// open FRI
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"2", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:5];// close

[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"5", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:6];// open MON
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"5", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:7];// close
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"6", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:8];// open TUE
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"6", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:9];// close
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"7", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:10];// open WED
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"7", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:11];// close
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"8", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:12];// open THU
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"8", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:13];// close
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"9", @"8", @"00", @"00", @"EST", @"Holiday list", nil ] atIndex:14];// open FRI
[usdMarketHours insertObject:[NSArray arrayWithObjects:@"2012", @"3", @"9", @"17", @"00", @"00", @"EST", @"", nil ] atIndex:15];// close


int USDarrayLength = [usdMarketHours count];  

int index0USD = 0;
int index1USD = 1;
int index2USD = 2;

int u = 0;
// ----------------------------------------------   START FOR LOOP   ---------------------------------------------------------->
for (u=0; u<USDarrayLength; u++) {
    NSDate *USDnow = [NSDate date]; 

    // ------------------------------------------------------->
    // Convert to timeA        

    NSString *USDyear = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:0];
    NSString *USDmonth = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:1];
    NSString *USDday = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:2];
    NSString *USDhour = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:3];
    NSString *USDminute = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:4];
    NSString *USDsecond = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:5];
    NSString *USDtimeZone = [[usdMarketHours objectAtIndex:index0USD] objectAtIndex:6];

    NSDateComponents *USDcompA = [[NSDateComponents alloc] init];
    [USDcompA setYear:[USDyear intValue]];
    [USDcompA setMonth:[USDmonth intValue]];
    [USDcompA setDay:[USDday intValue]];
    [USDcompA setHour:[USDhour intValue]];
    [USDcompA setMinute:[USDminute intValue]];
    [USDcompA setSecond:[USDsecond intValue]];
    [USDcompA setTimeZone:[NSTimeZone timeZoneWithAbbreviation:[NSString stringWithFormat:@"%@", USDtimeZone]]];

    USDcal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    USDtimeADate = [USDcal dateFromComponents:USDcompA];     

    // Using NSDateFormatter pointers, set format for array[]/GMT/Local times.

    // timeAFormatter for array date
    [USDtimeAFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeAFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:USDtimeZone]]; // Array Time Zone      

    [USDtimeAFormatterGMT setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeAFormatterGMT setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; // String "GMT"       

    [USDtimeAFormatterLocal setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
    [USDtimeAFormatterLocal setTimeZone:[NSTimeZone localTimeZone]]; // Local time         

    // ------------------------------------------------------->
    // Convert to timeB

    NSString *USDyearb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:0];
    NSString *USDmonthb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:1];
    NSString *USDdayb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:2];
    NSString *USDhourb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:3];
    NSString *USDminuteb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:4];
    NSString *USDsecondb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:5];
    NSString *USDtimeZoneb = [[usdMarketHours objectAtIndex:index1USD] objectAtIndex:6];

    NSDateComponents *USDcompB = [[NSDateComponents alloc] init];
    [USDcompB setYear:[USDyearb intValue]];
    [USDcompB setMonth:[USDmonthb intValue]];
    [USDcompB setDay:[USDdayb intValue]];
    [USDcompB setHour:[USDhourb intValue]];
    [USDcompB setMinute:[USDminuteb intValue]];
    [USDcompB setSecond:[USDsecondb intValue]];
    [USDcompB setTimeZone:[NSTimeZone timeZoneWithAbbreviation:[NSString stringWithFormat:@"%@", USDtimeZoneb]]];

    USDcalb = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    USDtimeBDate = [USDcalb dateFromComponents:USDcompB]; 

    [USDtimeBFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeBFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:USDtimeZoneb]]; // Array Time Zone

    [USDtimeBFormatterGMT setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeBFormatterGMT setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; // String "GMT" 

    [USDtimeBFormatterLocal setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
    [USDtimeBFormatterLocal setTimeZone:[NSTimeZone localTimeZone]]; // String "GMT"  


    // ----------------------------------------------------------------------------------->
    // Convert to timeC

    NSString *USDyearc = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:0];
    NSString *USDmonthc = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:1];
    NSString *USDdayc = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:2];
    NSString *USDhourc = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:3];
    NSString *USDminutec = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:4];
    NSString *USDsecondc = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:5];
    NSString *USDtimeZonec = [[usdMarketHours objectAtIndex:index2USD] objectAtIndex:6];

    NSDateComponents *USDcompC = [[NSDateComponents alloc] init];
    [USDcompC setYear:[USDyearc intValue]];
    [USDcompC setMonth:[USDmonthc intValue]];
    [USDcompC setDay:[USDdayc intValue]];
    [USDcompC setHour:[USDhourc intValue]];
    [USDcompC setMinute:[USDminutec intValue]];
    [USDcompC setSecond:[USDsecondc intValue]];
    [USDcompC setTimeZone:[NSTimeZone timeZoneWithAbbreviation:[NSString stringWithFormat:@"%@", USDtimeZonec]]];

    USDcalc = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    USDtimeCDate = [USDcalb dateFromComponents:USDcompC];   

    [USDtimeCFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeCFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:USDtimeZonec]]; // Array Time Zone

    [USDtimeCFormatterGMT setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; 
    [USDtimeCFormatterGMT setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; // String "GMT" 

    [USDtimeCFormatterLocal setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
    [USDtimeCFormatterLocal setTimeZone:[NSTimeZone localTimeZone]]; // String "GMT" 

    // ------------------------------------------------------------------------------------>  
    // create doubles, from timeIntervalSince1970. ex: 12345678945613.13489
    double timeAInterval = [USDtimeADate timeIntervalSince1970];
    double timeNowInterval = [USDnow timeIntervalSince1970];
    double timeBInterval = [USDtimeBDate timeIntervalSince1970]; 
    //double timeCInterval = [timeCDate timeIntervalSince1970];         

    // mathA = this is how long the market is open/closed. the before time.   
    // timeAInterval = array date before present time
    // timeNowInterval = date of present time
    // timeBInterval = array date of after present time
    // timeCInterval = array date of 2nd after present time

    // ------------------------------------------------------------------------------------>
    // if statement to find the correct array dates
    if((timeAInterval < timeNowInterval) && (timeBInterval > timeNowInterval))
    {
        // ------------------------------------------------------------------------------------>
        // Even index(i) are OPEN times, Odd index are CLOSED times.
        NSString *USDindex0Prefix = @"";   
        NSString *USDindex1Prefix = @"";     
        if(index0USD % 2 ==0)
        {
            // Market is presently -------------------> OPEN
            // NSLog(@"%i is even number", index0);
            //NSLog(@"MARKET IS OPEN");
            USDindex0Prefix = @"Closes : ";
            USDindex1Prefix = @"Opens : ";
            USDremainPrefix = @"Closes in: ";
            UIImage *image = [UIImage imageNamed:@"USD_flag.png"];
            [USDlightOpenOrClose setImage:image];
        }else{
            // Market is presently -------------------> CLOSED
            //NSLog(@"%i is odd number", index0);
            //NSLog(@"MARKET IS CLOSED");
            USDindex1Prefix = @"Closes : ";
            USDindex0Prefix = @"Opens : ";
            USDremainPrefix = @"Opens in: ";
            UIImage *image = [UIImage imageNamed:@"USD_flag_BW.png"];
            [USDlightOpenOrClose setImage:image];
        }              

        // ------------------------------------------------------------------------------------>
        // Math to seperate hour, minutes, seconds
        NSTimeInterval elapsedTime = [USDtimeBDate timeIntervalSinceNow];    
        div_t h = div(elapsedTime, 3600);
        int hours = h.quot;
        div_t m = div(h.rem, 60);
        int minutes = m.quot;
        int seconds = m.rem;

        // Remove negative sign if neg number. If not, do nothing: hours, minutes, seconds are int    
        if(hours<0){
            hours = hours * -1;
        }
        if(minutes<0){
            minutes = minutes * -1;
        }
        if(seconds<0){
            seconds = seconds * -1;
        }  
        // Formats the UITextField remaining time.
        if(hours <= 0){// hours less than or equal to 0
            USDRemainTime.text = [NSString stringWithFormat:@"%@ %.2dm %.2ds", USDremainPrefix,minutes, seconds];
            USDRemainTime.textColor = [UIColor blackColor];
            USDRemainTime.font = [UIFont systemFontOfSize:14];
        }
        if(hours > 0){// hours more than 0
            USDRemainTime.text = [NSString stringWithFormat:@"%@ %dh %.2dm ", USDremainPrefix,hours, minutes];
            USDRemainTime.textColor = [UIColor blackColor];
            USDRemainTime.font = [UIFont systemFontOfSize:14];
        }
        if((hours >= 1) && (hours < 10)){// hours between 1hr and 10hr
            USDRemainTime.text = [NSString stringWithFormat:@"%@ %.1dh %.2dm", USDremainPrefix ,hours, minutes];
            USDRemainTime.textColor = [UIColor blackColor];
            USDRemainTime.font = [UIFont systemFontOfSize:14];
        }
        if((hours <= 0) && (minutes < 5)){// less than 5 min
            // Less than 5 min, turn text red.
            USDRemainTime.text = [NSString stringWithFormat:@"%@ %.2dm %.2ds", USDremainPrefix, minutes, seconds];
            USDRemainTime.textColor = [UIColor redColor];
            USDRemainTime.font = [UIFont boldSystemFontOfSize:16];
        }

        // ------------------------------------------------------------------------------------>
        // Format timeA and timeB with NSDateFormatter. Use in text fields and labels
        NSDateFormatter *USDtimeAFormatted = [[NSDateFormatter alloc] init];            
        [USDtimeAFormatted setDateFormat:@"EEE. MMM. dd, yyyy HH:mm:ss z"]; 

        NSDateFormatter *USDtimeNoSeconds = [[NSDateFormatter alloc] init];
        [USDtimeNoSeconds setDateFormat:@"EEE. MMM. dd, yyyy HH:mm z"];


        // This sets the Open/Close labels to Country time(array time), GMT time, or local time
        // 0 = Country timezone (array timezone)
        // 1 = GMT timezone
        // 2 = local timezone
        int desiredFormat = 0;
        if(desiredFormat == 0){
            [USDtimeAFormatted setTimeZone:[NSTimeZone timeZoneWithAbbreviation:USDtimeZoneb]];
            NSString *USDfinalRemainb = [USDtimeAFormatted stringFromDate:USDtimeBDate];           
            USDStartTime.text = [NSString stringWithFormat:@"%@ %@", USDindex0Prefix, USDfinalRemainb];

            [USDtimeAFormatted setTimeZone:[NSTimeZone timeZoneWithAbbreviation:USDtimeZonec]];
            NSString *USDfinalRemainc = [USDtimeAFormatted stringFromDate:USDtimeCDate];           
            USDCloseTime.text = [NSString stringWithFormat:@"%@ %@", USDindex1Prefix, USDfinalRemainc];

            //[USDtimeNoSeconds setTimeZone:[NSTimeZone localTimeZone]];
            [USDtimeNoSeconds setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"EST"]];
            NSString *USDNowTime = [USDtimeNoSeconds stringFromDate:USDnow];           
            USDPresentTime.text = [NSString stringWithFormat:@"Present Time: %@",  USDNowTime];
        }
        if(desiredFormat == 1){
            [USDtimeAFormatted setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
            NSString *USDfinalRemainb = [USDtimeAFormatted stringFromDate:USDtimeBDate];           
            USDStartTime.text = [NSString stringWithFormat:@"%@ %@", USDindex0Prefix, USDfinalRemainb];

            [USDtimeAFormatted setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
            NSString *USDfinalRemainc = [USDtimeAFormatted stringFromDate:USDtimeCDate];           
            USDCloseTime.text = [NSString stringWithFormat:@"%@ %@", USDindex1Prefix, USDfinalRemainc];

            [USDtimeAFormatted setTimeZone:[NSTimeZone localTimeZone]];
            NSString *USDNowTime = [USDtimeAFormatted stringFromDate:USDnow];           
            USDPresentTime.text = [NSString stringWithFormat:@"Present Time: %@",  USDNowTime];
        }
        if(desiredFormat == 2){
            [USDtimeAFormatted setTimeZone:[NSTimeZone localTimeZone]];
            NSString *USDfinalRemainb = [USDtimeAFormatted stringFromDate:USDtimeBDate];           
            USDStartTime.text = [NSString stringWithFormat:@"%@ %@", USDindex0Prefix, USDfinalRemainb];

            [USDtimeAFormatted setTimeZone:[NSTimeZone localTimeZone]];
            NSString *USDfinalRemainc = [USDtimeAFormatted stringFromDate:USDtimeCDate];           
            USDCloseTime.text = [NSString stringWithFormat:@"%@ %@", USDindex1Prefix, USDfinalRemainc];

            [USDtimeAFormatted setTimeZone:[NSTimeZone localTimeZone]];
            NSString *USDNowTime = [USDtimeAFormatted stringFromDate:USDnow];           
            USDPresentTime.text = [NSString stringWithFormat:@"Present Time: %@",  USDNowTime];
        }



        // ------------------------------------------------------------------------------------>
        // disables the textField from a user interaction
        USDRemainTime.enabled = NO;
        [USDRemainTime setUserInteractionEnabled:NO];

    }else{

        index0USD++;
        index1USD++;
        index2USD++;
        // if incremented that means that we must check the next array to see if the present date is between two arrays
    }
}

} }

- (void)viewDidLoad

{ {

forexTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateForexTimer) userInfo:nil repeats:YES];
USDTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateUSDTimer) userInfo:nil repeats:YES];

[self.scrollView addSubview:self.contentView];
self.scrollView.contentSize = self.contentView.bounds.size;        
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

} }

well, probably it may be better to use just 1 timer and manage all scrolling inside it, but a better way (depending on what are you trying do do) could be just to use UIView animation block with animateWithDuration:animations: and let all the hard work to it. 好吧,可能最好只使用1个计时器并管理其中的所有滚动,但更好的方法(取决于你尝试做什么)可能只是使用UIView动画块与animateWithDuration:动画:并让所有努力工作。 what kind of animations are you doing with your UIViews? 你用你的UIViews做了什么样的动画?

I believe that the first problem is caused by doing too many operations (checks) on the main thread. 我认为第一个问题是由主线程上的太多操作(检查)引起的。 Since all UI operations (in your case, scrolling) are also handled on the main thread, they will only get called when the other checks have been finished. 由于所有UI操作(在您的情况下,滚动)也在主线程上处理,因此只有在其他检查完成时才会调用它们。 This might be the cause of the initial stutter you notice. 这可能是您注意到的最初口吃的原因。 The second problem is probably due to the way NSTimers work - they're not real-time. 第二个问题可能是由于NSTimers的工作方式 - 它们不是实时的。 Even if a timer's firing time has passed, it will only be called if the thread that is responsible for the timer is idle. 即使定时器的触发时间已经过去,只有在负责定时器的线程空闲时才会调用它。 So only once the view has stopped scrolling will the timer be checked. 因此,只有在视图停止滚动后才会检查计时器。

You could try adding the checks in a different thread and only call the main thread to update the UI elements if necessary. 您可以尝试在不同的线程中添加检查,并且只在必要时调用主线程来更新UI元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM