2009-04-09 2 views
0

問題があります。私は2000年から2000年までのレコード(典型的な数字)を持つことができるUITableを表示しようとしています。イントロスペクションでコードを最適化する方法+ iPhoneで重い割り当てを行う方法

私はSQLiteデータベースをアップルの連絡先アプリケーションに似ています。

私はスムーススクロールを得るために私が知っているすべてのトリックをしますが、私には問題があります。

データを50個のレコードブロックに読み込みます。次に、ユーザーがスクロールすると、リストを終了するまで次の50を要求します。

ただし、50個のレコードをロードすると、読み込みとスクロールで著しい「一時停止」が発生します。それ以外はうまく動作します。

は私が

私はdictsで同じデータをロードするコードを交換し、パフォーマンスの向上を持っていますが、私は指向私のオブジェクトを保つことができるかしら...など、不透明な細胞を持っているコードでそれを描き、データをキャッシュしますaproachし、実際のコードを改善する。

これは私がパフォーマンス上の問題があると思うのコードです:

-(NSArray *) loadAndFill: (NSString *)sql theClass: (Class)cls { 
     [self openDb]; 

     NSMutableArray *list = [NSMutableArray array]; 

     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

     DbObject *ds; 
     Class myClass = NSClassFromString([DbObject getTableName:cls]); 

     FMResultSet *rs = [self load:sql]; 

     while ([rs next]) { 
      ds = [[myClass alloc] init]; 
      NSDictionary *props = [ds properties]; 
      NSString *fieldType = nil; 
      id fieldValue; 

      for (NSString *fieldName in [props allKeys]) { 
       fieldType = [props objectForKey: fieldName]; 

       fieldValue = [self ValueForField:rs Name:fieldName Type:fieldType]; 

       [ds setValue:fieldValue forKey:fieldName]; 
      } 

      [list addObject :ds]; 

      [ds release]; 
     } 
     [rs close]; 

     [pool drain]; 
     return list; 
    } 

そして、私が主犯だと思います:

-(id) ValueForField: (FMResultSet *)rs Name:(NSString *)fieldName Type:(NSString *)fieldType { 
     id fieldValue = nil; 

     if ([fieldType isEqualToString:@"i"] || // int 
       [fieldType isEqualToString:@"I"] || // unsigned int 
       [fieldType isEqualToString:@"s"] || // short 
       [fieldType isEqualToString:@"S"] || // unsigned short 
       [fieldType isEqualToString:@"f"] || // float 
       [fieldType isEqualToString:@"d"]) // double 
     { 
      fieldValue = [NSNumber numberWithInt: [rs longForColumn:fieldName]]; 
     } 
     else if ([fieldType isEqualToString:@"B"]) // bool or _Bool 
     { 
      fieldValue = [NSNumber numberWithBool: [rs boolForColumn:fieldName]]; 
     } 
     else if ([fieldType isEqualToString:@"l"] || // long 
       [fieldType isEqualToString:@"L"] || // usigned long 
       [fieldType isEqualToString:@"q"] || // long long 
       [fieldType isEqualToString:@"Q"]) // unsigned long long 
     { 
      fieldValue = [NSNumber numberWithLong: [rs longForColumn:fieldName]]; 
     } 
     else if ([fieldType isEqualToString:@"c"] || // char 
       [fieldType isEqualToString:@"C"]) // unsigned char 

     { 
      fieldValue = [rs stringForColumn:fieldName]; 
      //Is really a boolean? 
      if ([fieldValue isEqualToString:@"0"] || [fieldValue isEqualToString:@"1"]) { 
       fieldValue = [NSNumber numberWithInt: [fieldValue intValue]]; 
      } 
     } 
     else if ([fieldType hasPrefix:@"@"]) // Object 
     { 
      NSString *className = [fieldType substringWithRange:NSMakeRange(2, [fieldType length]-3)]; 

      if ([className isEqualToString:@"NSString"]) { 
       fieldValue = [rs stringForColumn:fieldName]; 
      } 
      else if ([className isEqualToString:@"NSDate"]) { 
       NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; 
       [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"]; 
       NSString *theDate = [rs stringForColumn:fieldName]; 

       if (theDate) { 
        fieldValue = [dateFormatter dateFromString: theDate]; 
       } 
       else 
       { 
        fieldValue = nil; 
       } 

       [dateFormatter release]; 
      } 
      else if ([className isEqualToString:@"NSInteger"]) { 
       fieldValue = [NSNumber numberWithInt: [rs intForColumn :fieldName]]; 
      } 
      else if ([className isEqualToString:@"NSDecimalNumber"]) { 
       fieldValue = [rs stringForColumn :fieldName]; 
       if (fieldValue) { 
        fieldValue = [NSDecimalNumber decimalNumberWithString:[rs stringForColumn :fieldName]]; 
       } 
      } 
      else if ([className isEqualToString:@"NSNumber"]) { 
       fieldValue = [NSNumber numberWithDouble: [rs doubleForColumn:fieldName]]; 
      } 
      else 
      { 
       //Is a relationship one-to-one? 
       if (![fieldType hasPrefix:@"NS"]) { 
        id rel = class_createInstance(NSClassFromString(className), sizeof(unsigned)); 
        Class theClass = [rel class]; 
        if ([rel isKindOfClass:[DbObject class]]) { 
         fieldValue = [rel init]; 
         //Load the record... 
         NSInteger Id = [rs intForColumn:[theClass relationName]]; 
         if (Id>0) { 
          [fieldValue release]; 

          Db *db = [Db currentDb]; 

          fieldValue = [db loadById: theClass theId:Id]; 
         } 
        } 
       } else { 

        NSString *error = [NSString stringWithFormat:@"Err Can't get value for field %@ of type %@", fieldName, fieldType]; 

        NSLog(error); 
        NSException *e = [NSException 
             exceptionWithName:@"DBError" 
             reason:error 
             userInfo:nil]; 
        @throw e; 
       } 
      } 
     } 
     return fieldValue; 
    } 

答えて

0

あなたは「楽器」は使用してこのプログラムを実行することができますサンプラーツールを使用して問題がどこにあるかを把握します。 ValueForFieldをより小さな呼び出しに書き換えて、必要ならばどの部分がボトルネックかを確認することができます。

その他の可能性: データが静的であれば、C配列(特にintとbool)に一度に読み込むことができます。同じ値がたくさんある場合は、同様のオブジェクトを共有することができます。たとえば、テーブルに20,000行、カラムに同じ文字列がある場合は、1つの文字列を作成して共有できます。

0

パフォーマンス上の問題は、decimalNumberWithStringと同じように見えます。

コードから削除すると、遅れがそれよりもずっと小さくなります。

は、私は、通貨経営管理論:(

+0

ためNSDecimalNumberを必要とするしかし、あなたは本当に、たとえば、あなたが保存できませんでした?ペニー(またはセンターボまたは何でも)を表す64ビット固定小数点数を、それを必要としないという悪いですか?それでしょう分数ペニーを気にしないと仮定すれば、世界のGDPを表すのに十分な以上になります。 – Crashworks

関連する問題