2011-05-30 25 views
1

我需要通过值,而不是重点进行排序,我觉得....的OBJ-C,iOS的,我如何排序值,而不是关键,sortedArrayUsingSelector,目前@selector(比较:)]

继承人在那里我填写我的arrarys

const char *sql = "select cid, category from Categories ORDER BY category DESC"; 
sqlite3_stmt *statementTMP; 

int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL); 
if(error_code == SQLITE_OK) { 
    while(sqlite3_step(statementTMP) == SQLITE_ROW) 
    { 
     int cid = sqlite3_column_int(statementTMP, 0); 
     NSString *category = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)]; 

     NSArray *arr=[[NSArray alloc]initWithObjects:category,nil]; 

     [arrayTmp setObject:arr forKey:[NSString stringWithFormat:@"%i",cid]]; 
     [self.cidList addObject:[NSString stringWithFormat:@"%i",cid]]; 

     [category release]; 
     [arr release]; 
    } 
} 
sqlite3_finalize(statementTMP); 
sqlite3_close(database); 

self.allCategories = arrayTmp; 
[arrayTmp release]; 

继承人数组重新排序的方法。

- (void)resetSearch { 

NSMutableDictionary *allCategoriesCopy = [self.allCategories mutableDeepCopy]; 
self.Categories = allCategoriesCopy; 
[allCategoriesCopy release]; 
NSMutableArray *keyArray = [[NSMutableArray alloc] init]; 
[keyArray addObject:UITableViewIndexSearch]; 
[keyArray addObjectsFromArray:[[self.allCategories allKeys] 
           sortedArrayUsingSelector:@selector(compare:)]]; 
self.keys = keyArray; 
[keyArray release]; 
} 

这是一个问题,我已经有一段时间,我最后一次看这个我能找到一个altervative到sortedArrayUsingSelector比较?

编辑

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

NSUInteger section = [indexPath section]; 
NSUInteger row = [indexPath row]; 

NSString *key = [keys objectAtIndex:section]; 
NSArray *nameSection = [Categories objectForKey:key]; 

static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier"; 

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: 
         SectionsTableIdentifier ]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
            reuseIdentifier: SectionsTableIdentifier ] autorelease]; 
} 

cell.textLabel.text = [nameSection objectAtIndex:row]; 
return cell; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

NSUInteger section = [indexPath section]; 
NSUInteger row = [indexPath row]; 

NSString *key = [keys objectAtIndex:section]; 
NSArray *nameSection = [Categories objectForKey:key]; 

NSLog(@"the selected cid is = %i",[key intValue]); 

selectButton.enabled = YES; 
} 

有人吗?

+2

只有受虐者直接在Objective-C中使用SQLite C API。 [使用FMDB](http://github.com/ccgus/fmdb)(一个SQLite包装器)或[CoreData](http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/ cdProgrammingGuide.html)(一个对象图管理器)。 – 2011-05-30 20:15:23

+0

@Dave,它适用于我,我有FMDB的问题,从未尝试CoreData – Jules 2011-05-30 20:24:02

+1

@Jules - 你可能想详细说明你的问题是什么。你期望什么行为,你看到了什么确切的行为。除非出现明显的错误,否则很难从代码示例中推断出问题所在。 – TechZen 2011-06-03 03:19:08

回答

0

如果我理解正确,那么你想这样做,从数据库中获取的类别上&显示它是什么带有字母顺序排序的tableView,右边的索引&顶部的搜索栏。理想情况下,您希望显示“联系人”应用程序类型的视图。如果这是正确的,使用下面的代码取出来自DB &项目重建(或复位)它 -

const char *sql = "select cid, category from Categories ORDER BY category DESC"; 
sqlite3_stmt *statementTMP; 

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

int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL); 
if(error_code == SQLITE_OK) { 
    while(sqlite3_step(statementTMP) == SQLITE_ROW) { 
     int cid = sqlite3_column_int(statementTMP, 0); 
     NSString *category = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)]; 

     NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 
     [dict setObject:category forKey:@"Category"]; 
     [dict setObject:[NSNumber numberWithInt:cid] forKey:@"CID"]; 

     [arrayTmp addObject:dict]; 
     [dict release]; 
     [category release]; 
    } 
} 

sqlite3_finalize(statementTMP); 
sqlite3_close(database); 

self.allCategories = arrayTmp; 
[arrayTmp release]; 

,然后使用这个功能重建项目 -

- (void)rebuildItems { 
    NSMutableDictionary *map = [NSMutableDictionary dictionary]; 

    for (int i = 0; i < allCategories.count; i++) { 
     NSString *name = [[allCategories objectAtIndex:i] objectForKey:@"Category"]; 
     NSString *letter = [name substringToIndex:1]; 
     letter = [letter uppercaseString]; 

     if (isdigit([letter characterAtIndex:0])) 
       letter = @"#"; 

     NSMutableArray *section = [map objectForKey:letter]; 
     if (!section) { 
      section = [NSMutableArray array]; 
      [map setObject:section forKey:letter]; 
     } 
     [section addObject:[allCategories objectAtIndex:i]]; 
    } 

    [_items release]; 
    _items = [[NSMutableArray alloc] init]; 
    [_sections release]; 
    _sections = [[NSMutableArray alloc] init]; 

    NSArray* letters = [map.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 
    for (NSString* letter in letters) { 
     NSArray* items = [map objectForKey:letter]; 
     [_sections addObject:letter]; 
     [_items addObject:items]; 
    } 
} 

现在,在的tableView显示的项目,使用下面的方法 -

#pragma mark - 
#pragma mark Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView { 
    if (_sections.count) 
     return _sections.count; 
    else 
     return 1; 
} 

- (NSInteger)tableView:(UITableView*)tableView sectionForSectionIndexTitle:(NSString *)title 
       atIndex:(NSInteger)index { 

    if (tableView.tableHeaderView) { 
     if (index == 0) { 
      [tableView scrollRectToVisible:tableView.tableHeaderView.bounds animated:NO]; 
      return -1; 
     } 
    } 

    NSString* letter = [title substringToIndex:1]; 
    NSInteger sectionCount = [tableView numberOfSections]; 
    for (NSInteger i = 0; i < sectionCount; i++) { 
     NSString* section = [tableView.dataSource tableView:tableView titleForHeaderInSection:i]; 
     if ([section hasPrefix:letter]) { 
      return i; 
     } 
    } 

    if (index >= sectionCount) { 
     return sectionCount-1; 
    } else { 
     return index; 
    } 
} 


- (NSArray*)lettersForSectionsWithSearch:(BOOL)withSearch withCount:(BOOL)withCount { 
    if (isSearching) 
     return nil; 

    if (_sections.count) { 
     NSMutableArray* titles = [NSMutableArray array]; 
     if (withSearch) { 
      [titles addObject:UITableViewIndexSearch]; 
     } 
     for (NSString* label in _sections) { 
      if (label.length) { 
       NSString* letter = [label substringToIndex:1]; 
       [titles addObject:letter]; 
      } 
     } 
     if (withCount) { 
      [titles addObject:@"#"]; 
     } 
     return titles; 
    } else { 
     return nil; 
    } 
} 


- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 
    return [self lettersForSectionsWithSearch:YES withCount:NO]; 
} 


- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section { 
    if (_sections.count) { 
     NSArray* items = [_items objectAtIndex:section]; 
     return items.count; 
    } else { 
     return _items.count; 
    } 
} 


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
    if (_sections.count) 
     return [_sections objectAtIndex:section]; 

    return nil; 
} 


- (id)tableView:(UITableView *)tableView objectForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (_sections.count) { 
     NSArray *section = [_items objectAtIndex:indexPath.section]; 
     return [section objectAtIndex:indexPath.row]; 
    } else { 
     return [_items objectAtIndex:indexPath.row]; 
    } 
} 


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    // Create your UITableViewCell. 

    // Configure the cell. 
    NSDictionary *dict = [self tableView:tableView objectForRowAtIndexPath:indexPath]; 
    cell.textLabel.text = [dict objectForKey:@"Category"]; 
      cell.detailTextLabel.text = [NSString stringWithFormat:%d, [[dict objectForKey:@"CID"] intValue]]; 
    return cell; 
} 

#pragma mark - 
#pragma mark Table view delegate 


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    if (isSearching) 
     return nil; 

    NSString *title = @""; 
    if (_sections.count) {  
     title = [[_sections objectAtIndex:section] substringToIndex:1]; 
    } else { 
     return nil; 
    } 

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)]; 
    view.backgroundColor = [UIColor colorWithRed:(58/255.0) green:(27/255.0) blue:(6/255.0) alpha:1.0]; 

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 1, 50, 18)]; 
    label.textColor = [UIColor whiteColor]; 
    label.backgroundColor = [UIColor clearColor]; 
    label.font = [UIFont boldSystemFontOfSize:17.0]; 
    label.text = title; 

    [view addSubview:label]; 
    [label release]; 

    return [view autorelease]; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSDictionary *dict = [self tableView:tableView objectForRowAtIndexPath:indexPath]; 

    NSLog(@"selected row id:%d, name:%@", [dict objectForKey:@"Category"], [[dict objectForKey:@"CID"] intValue]); 
} 

其余部分是实现UISearchBarDelegate和实施的tableView的搜索可使用BEL完成ow代码:

- (void)searchBar:(UISearchBar *)searchbar textDidChange:(NSString *)searchText { 

    [_sections removeAllObjects]; 
    [_items removeAllObjects]; 

    if([searchText isEqualToString:@""] || searchText == nil) { 
     [self rebuildItems]; 
     return; 
    } 

    NSInteger counter = 0; 
    for(NSDictionary *dict in allCategories) { 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     NSRange r = [[dict objectForKey:@"Category"] rangeOfString:searchText options:NSCaseInsensitiveSearch]; 
     if(r.location != NSNotFound) { 
      if(r.location == 0) { 
       [_items addObject:dict]; 
      } 
     } 
     counter++; 
     [pool release]; 
    } 

    [contactList reloadData]; 
} 

希望这是你在找什么。

+0

我从你的代码中得到了很多错误,heres其中的一些......'NSMutableDictionary'可能不会响应'-addObject:','NSDictionary'可能不会响应'-objectAtIndex:','_items'未声明(首次在这个函数中使用),'_sections'未声明(在这个函数中首次使用),'isSearching'未声明(首次在这个函数中使用),错误:'cell'未声明(首次在这个函数中使用) '-refreshContactsList',错误:'allContacts'未声明(首次在此函数中使用),错误:'contactList'未声明(首次在此函数中使用) – Jules 2011-06-07 08:09:24

+0

我认为可以理解_sections&_items是类NSMutableArray的全局对象。还可以将contactList替换为您的UITableView的对象。就像我们从你的代码片断中了解的那样,所有的Categories都是一个属性对象,并且必须被合成。 – Sagar 2011-06-07 08:37:01

+0

NSMutableArray * arrayTmp = [[NSMutableArray alloc] init];已经在开始的代码中定义了。另外,修复refreshContactsList&allContacts方法调用的错误,并用适当的调用替换它。 isSearching又是一个全局布尔值。从UISearchBar开始搜索时应该设置它。 – Sagar 2011-06-07 08:42:34

1

也许你正在寻找NSSortDescriptor(以及相应的排序方法,-[NSArray sortedArrayUsingDescriptors])和朋友吗?

+0

谢谢,我不知道如何实现这个? – Jules 2011-05-30 14:24:38

3

使用-sortedArrayUsingComparator:(或-sortedArrayUsingFunction:context:如果您不能使用块)。例如:

NSDictionary *categories = [self allCategories]; 
NSArray *keysSortedByValue = [[categories allKeys] sortedArrayUsingComparator: 
^(id left, id right) { 
    id lval = [categories objectForKey:left]; 
    id rval = [categories objectForKey:right]; 
    return [lval compare:rval]; 
}]; 
+0

@Jules请更精确。它以什么方式失败?有没有错误信息?如果是这样,每条错误消息的全文是什么? – 2011-05-30 14:26:22

+0

@Jules这只是一个可变性问题。你需要相当于一个Obj-C转换为可变实例:'[[keysSortedByValue mutableCopy] autorelease]',或者使用截图中的变量'self.keys = [[keyArray mutableCopy] autorelease]'。 – 2011-05-30 14:46:30

+0

@Jules或者(更清洁),'[[self key] setArray:allKeys]'。这只是用'allKeys'中的所有键替换当前'keys'数组中的键,这意味着您可以跳过取消分配旧'keys'数组并复制新数组。更好。 – 2011-05-30 14:48:24

4

您明显尝试构建一个数组以供在-[UITableviewDatasource sectionIndexTitlesForTableView:]中使用。因此,你需要看起来像这样(伪代码)的数组:

[UITableViewIndexSearch, 0_sectionTitle, 1_sectionTitle, 2_sectionTitle, ...] 

我觉得你眼前的问题是,你尝试之前UITableViewIndexSearch字符串常量添加到阵列您排序哪些使它不可能作为第一个元素,除非你的其他元素排序在U以下。

修复很简单,只需在排序后添加常量即可。

NSMutableArray *secIdx=[NSMutableArray arrayWithCapacity:[[self.allCategories allKeys] count]]; 
    [secIdx addObjectsFromArray:[self.allCategories allKeys]]; 
    [secIdx sortUsingSelector:@selector(compare:)]; 
    [secIdx insertObject:UITableViewIndexSearch atIndex:0]; 
    self.keys=secIdx; 

注意secIdx会被自动释放,所以你不必释放它:当你在它你可以清洁代码了。

除了这个问题,你的代码还有很多不必要/危险的元素,会让你的应用变得脆弱而难以维护。

  1. 对于可以使用自动发布的便利方法的对象,您正在使用很多init。 'init`s可以缓解内存泄漏的风险,但是并不会带来任何好处。
  2. 您需要在对象中包装标量值,以便在集合中轻松管理它们。
  3. 您正在使用不必要的数组。

您可以改写的第一个块,像这样:

const char *sql = "select cid, category from Categories ORDER BY category DESC"; 
sqlite3_stmt *statementTMP; 

int error_code = sqlite3_prepare_v2(database, sql, -1, &statementTMP, NULL); 
if(error_code == SQLITE_OK) { 
    NSNumber *cidNum; //... move variable declerations outside of loop 
    NSString *category; //.. so they are not continously recreated 
    [self.allCategories removeAllObjects]; //... clears the mutable dictionary instead of replacing it 
    while(sqlite3_step(statementTMP) == SQLITE_ROW){ 
     cidNum=[NSNumber numberWithInt:(sqlite3_column_int(statementTMP, 0))]; 
     category=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)]; 
     //... adding the autoreleased category and cidNum to array/dictionary automatically retains them 
     [self.allCategories addObject:category forKey:cidNum]; 
     [self.cidList addObject:cidNum]; 

     //[category release]; ... no longer needed 
     //[arr release]; ... no longer needed 
    } 
} 
sqlite3_finalize(statementTMP); 
sqlite3_close(database); 

//self.allCategories = arrayTmp; ... no longer needed 
//[arrayTmp release]; ... no longer needed 
+0

我曾推断'self.allCategories'是一个NSMutableDictionary。如果它只是一个NSDictionary,则需要将该属性更改为可变字典或使用临时可变字典,然后转换为该属性。我建议只使用可变字典开始,除非你期望你的列表有成千上万个元素。 – TechZen 2011-06-03 13:36:47

+0

我无法从这些小代码片断中知道发生了什么。我不知道什么变量/财产持有什么数据和原因。如果你喜欢,你可以发布一个链接到头文件(.h)和实现(.m)文件,我可以看看。或者,您可以通过电子邮件将它们发送给我(单击电子邮件徽章上的我的名字。) – TechZen 2011-06-03 15:01:52

+0

@Jules - 我还没有收到任何东西。这是tech .com在我点com。 – TechZen 2011-06-04 12:52:46

0

在您的排序函数u应该试试这个:

NSArray *cntxt; //im not sure this is the correct type that ur using on keyArray 
[keyArray addObjectsFromArray:[self.allCategories allKeys]]; 
[keyArray sortUsingFunction:compareFunction context:cntxt]; 

而且比较修改功能,您的需求

NSInteger compareFunction(id x, id y, void *context) { 
    //NSArray *ctxt = context; 
    NSArray *c1 = x; 
    NSArray *c2 = y; 

    if ([c1 value] < [c2 value]) 
     return NSOrderedDescending; 
    else if ([c1 value] > [c2 value]) 
     return NSOrderedAscending; 
    else 
     return NSOrderedSame; 
} 

编辑:在阅读您的意见和后r在你的代码elooking,好像你keyArray作为类型的NSString的对象,所以你应该改变:

NSInteger compareFunction(id x, id y, void *context) { 
    //NSString *ctxt = context; 
    NSString *c1 = x; 
    NSString *c2 = y; 
    NSComparisonResult result; 
    result = [c1 compare:c2]; 

    if (result<0) 
     return NSOrderedAscending; 
    else if (result>0) 
     return NSOrderedDescending; 
    else 
     return NSOrderedSame; 
} 
+0

感谢@iruleonu,我收到了一些警告'NSArray可能不会响应'value'。我真的希望这有效:) – Jules 2011-06-07 06:54:24

+0

keyArray是NSMutableArray,如我的问题所示。 – Jules 2011-06-07 07:23:28

+0

我只写了[c1值]作为例子。这个比较将取决于你的NSArray keyArray包含的对象的类型。 – iruleonu 2011-06-07 08:46:43

相关问题