UIScrollView滚动不流畅?

时间:2012-03-04 16:39:20

标签: iphone ios5 uiscrollview nstimer

我有一个iPhone应用程序,它有10个NSTimer个函数,可以在滚动的视图上每隔0.5秒检查一次。每个计时器有3个标签,1个文本字段和1个UIImageView。所有30个标签,10个文本字段和10个UIImageViews都需要滚动 问题1 是视图滚动不流畅。我在这里看到了一些建议,然后尝试了没有成功。当你开始滚动时,它需要一瞬间开始,然后它跳跃大约150个像素然后它开始滚动。
问题2 是在滚动时,NSTimer不会更新文本字段和标签。当您停止滚动时,字段会跳转到正确的时间。这对于iPhone来说还是要处理的还是我缺少的东西?

我添加了一些“粗鲁”的代码。这只是一个每0.5秒检查一次的NSTimer。我也发布了所有指针,并在viewDidUnload中设置为nil。日期不同,他们将在假日信息中添加假日信息,并在以后的数组中添加更多信息。

更新:我在iPhone 4上运行了这个应用程序,它顺利。然而,在iPhone模拟器中 IS 平滑。

-(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.

}

2 个答案:

答案 0 :(得分:1)

好吧,可能最好只使用1个计时器并管理其中的所有滚动,但更好的方法(取决于你尝试做什么)可能只是使用带有animateWithDuration的UIView动画块:动画:和让所有努力工作吧。 你用你的UIViews做了什么样的动画?

答案 1 :(得分:0)

我认为第一个问题是由主线程上的操作(检查)过多引起的。由于所有UI操作(在您的情况下,滚动)也在主线程上处理,因此只有在其他检查完成时才会调用它们。这可能是您注意到的最初口吃的原因。 第二个问题可能是由于NSTimers的工作方式 - 它们不是实时的。即使定时器的触发时间已经过去,只有在负责定时器的线程空闲时才会调用它。因此,只有在视图停止滚动后才会检查计时器。

您可以尝试在不同的线程中添加检查,并且只在必要时调用主线程来更新UI元素。