2011-04-26 82 views
3

我有下面的代碼,將JSON字符串解碼爲一個對象數組,然後可以在UITableView中使用。優化慢代碼 - 枚舉字典

起初我以爲JSON解碼是慢的部分,但它似乎並不像「字典完成」幾乎立即出現。

有關如何讓代碼更快一點的任何想法?

-(void)parseJSON:(NSString *)jsonData{ 

    NSLog(@"Start parsing"); 
    NSDictionary *deserializedData = [jsonData objectFromJSONString]; 
    NSLog(@"Dictionary Done"); 

    NSArray *flights = [deserializedData valueForKeyPath:@"flights.flight"]; 
    NSMutableArray *localArray = [[NSMutableArray alloc] init ]; 
    NSString *lastFlightno [email protected]""; 

    for (NSDictionary *flight in flights){ 

     ArchiveFlight *aFlight = [[ArchiveFlight alloc] initWithFlightno:[flight objectForKey:@"flightno"] route:[flight objectForKey:@"route"]]; 
     aFlight.flightID = [flight objectForKey:@"primary_key"]; 
     aFlight.timeStamp = [aFlight niceDate:[flight objectForKey:@"timestamp"]]; 

     if (![lastFlightno isEqualToString:aFlight.flightno]) { 
      [localArray addObject:aFlight]; 
     } 

     lastFlightno =aFlight.flightno; 
     [aFlight release]; 
    } 
    NSLog(@"End Parsing"); 
    [self loadupTable:localArray]; 
    self.flightArray = localArray; 
    [localArray release]; 

} 

編輯:添加時間戳

時間戳如下NSLogs的...

2011-04-26 13:22:36.104 App[1778:707] Finished request 
2011-04-26 13:22:36.109 App[1778:707] Start parsing 
2011-04-26 13:22:36.128 App[1778:707] Dictionary Done 
2011-04-26 13:22:37.713 App[1778:707] End Parsing 

樣品的JSON的...

{"flights":[{"flight":{"flightno":"RYR54WP","timestamp":"2011-04-26 12:13:04","route":"EGNX-LEAL","primary_key":"836453"}},{"flight":{"flightno":"RYR24LU","timestamp":"2011-04-26 09:14:03","route":"EVRA-EGNX","primary_key":"831318"}},{"flight":{"flightno":"RYR39WH","timestamp":"2011-04-26 05:33:03","route":"EGNX-EVRA","primary_key":"825492"}},{"flight":{"flightno":"RYR7PX","timestamp":"2011-04-25 20:07:03","route":"LELC-EGNX","primary_key":"816703"}},{"flight":{"flightno":"RYR2VB","timestamp":"2011-04-25 16:57:06","route":"EGNX-LELC","primary_key":"810900"}},{"flight":{"flightno":"RYR3JN","timestamp":"2011-04-25 12:36:04","route":"GCTS-EGNX","primary_key":"802631"}},{"flight":{"flightno":"RYR8GV","timestamp":"2011-04-25 06:07:03","route":"EGNX-GCTS","primary_key":"792945"}},{"flight":{"flightno":"RYR82QR","timestamp":"2011-04-24 19:42:04","route":"EPKK-EGNX","primary_key":"783306"}},{"flight":{"flightno":"RYR51PV","timestamp":"2011-04-24 16:31:05","route":"EGNX-EPKK","primary_key":"777835"}},{"flight":{"flightno":"RYR53AQ","timestamp":"2011-04-24 14:09:05","route":"LIME-EGNX","primary_key":"773572"}},{"flight":{"flightno":"RYR1CX","timestamp":"2011-04-24 11:02:05","route":"EGNX-LIME","primary_key":"768285"}},{"flight":{"flightno":"RYR9ZW","timestamp":"2011-04-24 08:21:04","route":"LEGE-EGNX","primary_key":"764624"}},{"flight":{"flightno":"RYR63BC","timestamp":"2011-04-24 05:48:02","route":"EGNX-LEGE","primary_key":"761726"}},{"flight":{"flightno":"RYR7PX","timestamp":"2011-04-23 19:39:03" 

格式化樣本:

{ 
    "flights":[ 
     { 
     "flight":{ 
      "flightno":"RYR54WP", 
      "timestamp":"2011-04-26 12:13:04", 
      "route":"EGNX-LEAL", 
      "primary_key":"836453" 
     } 
     }, 
     { 
     "flight":{ 
      "flightno":"RYR24LU", 
      "timestamp":"2011-04-26 09:14:03", 
      "route":"EVRA-EGNX", 
      "primary_key":"831318" 
     } 
     } 
    ] 
} 

編輯2:

因此,這裏是 「niceDate」,是造成減速!

-(NSString *)niceDate:(NSString *)oldDate{ 
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init]autorelease]; 
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 
    NSDate *sourceDate = [formatter dateFromString:oldDate]; 
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; 
    [dateFormatter setDateStyle:NSDateFormatterFullStyle]; 
    [dateFormatter setTimeStyle:NSDateFormatterLongStyle]; 
    NSString *timeString = [dateFormatter stringFromDate:sourceDate]; 
    return [NSString stringWithFormat:@"%@",timeString]; 
} 
+0

您是否提供了一些性能分析時間戳來查看哪一部分花費最多時間? – 2011-04-26 12:16:45

+0

增加了一些時間戳,但不能真正在循環中插入一些沒有真正放慢速度的內容! – 2011-04-26 12:25:13

+0

我們在談論多少次迭代?你可以輸入一些日誌代碼,只是看看你的循環在第一次10/50/100迭代中的效果如何。也許由於某種原因,性能會下降? – 2011-04-26 12:30:23

回答

3

浮現在腦海中有些事情:

NSArray *flights = [deserializedData valueForKeyPath:@"flights.flight"]; 

你需要使用KVC?你的JSON數據的結構是什麼?

ArchiveFlight *aFlight = [[ArchiveFlight alloc] initWithFlightno:[flight objectForKey:@"flightno"] route:[flight objectForKey:@"route"]]; 
aFlight.flightID = [flight objectForKey:@"primary_key"]; 
aFlight.timeStamp = [aFlight niceDate:[flight objectForKey:@"timestamp"]]; 

你總是創建ArchiveFlight實例和解析時間戳...

if (![lastFlightno isEqualToString:aFlight.flightno]) { 
     [localArray addObject:aFlight]; 
    } 

...即使你沒有這樣做,所有的時間。取決於你有多少重複的flightnos,這可能會引起顯着的差異。

爲什麼不讀[flight objectForKey:@"flightno"],將它與lastFlightno進行比較,當且僅當它們不同時,創建一個實例,將其添加到數組中並釋放它?


編輯:請嘗試以下KVC-免費代碼:

NSArray *flights = [deserializedData objectForKey:@"flights"]; 
NSMutableArray *localArray = [[NSMutableArray alloc] init ]; 
NSString *lastFlightno [email protected]""; 

for (NSDictionary *flightWrapper in flights) { 
    NSDictionary *flight = [flightWrapper objectForKey:@"flight"]; 
    NSString *flightno = [flight objectForKey:@"flightno"]; 

    if (! [flightno isEqual:lastFlightno]) { 
     // create instance, add it to the array, release the instance 
    } 
} 

編輯:你創建和(自動)發佈這個方法裏面NSDateFormatter兩個實例。一般情況下,這樣可以,但是由於執行次數大於1K,因此需要考慮兩個因素:a)創建/使用/釋放這兩個實例的次數大於1K次,實際上,如果沒有兩次,則會出現b )你應該在你的循環中使用一個autorelease池。

您應該使此方法成爲類方法(或函數),因爲它不依賴於該類的實例的狀態。您的格式化程序將是類(靜態)變量。例如:

@implementation ArchiveFlight 

static NSDateFormatter *formatter1; // choose better names! 
static NSDateFormatter *formatter2; 

+ (void)initialize { 
    if (self == [ArchiveFlight class]) { 
     formatter1 = [[NSDateFormatter alloc] init]; 
     [formatter1 setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 

     formatter2 = [[NSDateFormatter alloc] init]; 
     [formatter2 setDateStyle:NSDateFormatterFullStyle]; 
     [formatter2 setTimeStyle:NSDateFormatterLongStyle]; 
    } 
} 

+ (NSString *)niceDate:(NSString *)oldDate { 
    NSDate *sourceDate = [formatter1 dateFromString:oldDate]; 
    NSString *timeString = [formatter2 stringFromDate:sourceDate]; 
    return timeString; 
    // why +stringWithFormat:? It’s not necessary! 
    // return [NSString stringWithFormat:@"%@",timeString]; 
} 

這修復項),但你因爲你使用回報Cocoa方法自動釋放對象真正應該使用自動釋放池的循環內。通過爲循環的每次迭代使用自動釋放池,可以減少代碼的內存佔用量 - 儘管如此,也可能會降低性能。我建議你嘗試使用和不使用內部自動釋放池。

for (NSDictionary *flightWrapper in flights) { 
    NSAutoreleasePool *pool = [NSAutoreleasePool new]; 

    … 

    [pool drain]; 
} 
+0

謝謝,我已經將JSON的樣本添加到了原始問題中....沒有多少重複的flightno,但是確實有一個很好的簡單修復,確實會刮掉一點點! 我認爲它的大部分是在KVC上,有沒有另一種方式? – 2011-04-26 12:43:02

+0

@Lee我已經更新了答案。 – 2011-04-26 12:49:37

+0

謝謝,這是一個更快一點。 1.2秒現在做循環語句。仍然有點太長,無法理解爲什麼當通過網絡和JSONKit的請求做到這一切非常快!混亂! – 2011-04-26 13:03:00