我正在构建我的第一个应用程序,它是一个简单的即时消息应用程序,允许用户向其合作伙伴发送即时更新,或从其合作伙伴请求更新(一对一)
“消息”区域有3种类型的消息,按时间顺序列出(使用3种不同颜色区分):
当用户点击消息屏幕时,将执行以下查询以调用您的所有消息。我现在只有6个测试用户,数据库中有大约150条消息,有时这个屏幕加载所有消息需要7-8秒。
任何人都可以建议我如何改进这个区域/查询:
// ALL VIEW
#import "AllTableView.h"
@implementation AllTableView
@synthesize historyDelegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_refreshControl = [[UIRefreshControl alloc] init];
[self addSubview:_refreshControl];
[_refreshControl addTarget:self action:@selector(initTableData) forControlEvents:UIControlEventValueChanged];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
*/
- (NSArray *)sortedArray:(NSArray *)array
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:LOC_TIME ascending:YES];
return [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
}
- (void)initTableData
{
self.delegate = self;
self.dataSource = self;
//_arrayDatas = [[NSMutableArray alloc] init];
NSMutableArray *tmpArray = [[NSMutableArray alloc] init];
NSString *usersPhone = [[NSUserDefaults standardUserDefaults] objectForKey:USER_PREFIX];
ShowWaitView1(YES, self);
// received
PFQuery *receiveLoc = [PFQuery queryWithClassName:PARSE_TABLE_CALL];
[receiveLoc whereKey:PARSE_CALL_STATUS equalTo:@"Sent"];
[receiveLoc whereKey:PARSE_CALL_TO equalTo:usersPhone];
// sent
PFQuery *sentLoc = [PFQuery queryWithClassName:PARSE_TABLE_CALL];
[sentLoc whereKey:PARSE_CALL_STATUS equalTo:@"Sent"];
[sentLoc whereKey:PARSE_CALL_FROM equalTo:usersPhone];
// received request
PFQuery *receiveReq = [PFQuery queryWithClassName:PARSE_TABLE_CALL];
[receiveReq whereKey:PARSE_CALL_TO equalTo:usersPhone];
[receiveReq whereKey:PARSE_CALL_STATUS equalTo:@"Request"];
PFQuery *query = [PFQuery orQueryWithSubqueries:@[receiveLoc, sentLoc, receiveReq]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *obj in objects) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSDate *dbDate = (NSDate *)[obj createdAt];
[dict setObject:dbDate forKey:LOC_TIME];
[dict setObject:obj[PARSE_CALL_FROM] forKey:LOC_PHONE];
[dict setObject:obj[PARSE_CALL_TO] forKey:LOC_TOPHONE];
[dict setObject:[self getNameFromPhoneInFriends:obj[PARSE_CALL_FROM]] forKey:LOC_USER];
[dict setObject:[self getNameFromPhoneInFriends:obj[PARSE_CALL_TO]] forKey:LOC_TONAME];
[dict setObject:obj[PARSE_CALL_LOCTITLE] forKey:LOC_NAME];
[dict setObject:obj[PARSE_CALL_LAT] forKey:LOC_LAT];
[dict setObject:obj[PARSE_CALL_LNG] forKey:LOC_LONG];
[dict setObject:obj[PARSE_CALL_MSG] forKey:LOC_MSG];
[dict setObject:obj[PARSE_CALL_ISOPEN] forKey:LOC_ISOPEN];
[dict setObject:obj[PARSE_CALL_BARPOS] forKey:LOC_BARPOS];
[dict setObject:obj[PARSE_CALL_STATUS] forKey:PARSE_CALL_STATUS];
if (obj[PARSE_CALL_TRACKING]) {
[dict setObject:obj[PARSE_CALL_TRACKING] forKey:LOC_TRACKING];
}
PFFile *imageFile = obj[PARSE_CALL_IMAGE];
if (imageFile) {
NSData *data = [imageFile getData];
[dict setObject:data forKey:LOC_IMAGE];
}
[tmpArray addObject:dict];
}
_arrayDatas = [[NSMutableArray alloc] initWithArray:[self sortedArray:tmpArray]];
ShowWaitView1(NO, self);
[self reloadData];
[_refreshControl endRefreshing];
} else {
NSLog(@"WARNING: Request query failed");
}
}];
}
- (NSString *)getNameFromPhoneInFriends:(NSString *)phone
{
NSArray *array = [[NSUserDefaults standardUserDefaults] objectForKey:FRIENDS_LIST];
if (array && array.count) {
for (NSDictionary *dict in array) {
if ([[dict objectForKey:LOC_PHONE] isEqualToString:phone]) {
return [dict objectForKey:LOC_USER];
}
}
}
array = [[NSUserDefaults standardUserDefaults] objectForKey:GUARDIANS_LIST];
if (array && array.count) {
for (NSDictionary *dict in array) {
if ([[dict objectForKey:LOC_PHONE] isEqualToString:phone]) {
return [dict objectForKey:LOC_USER];
}
}
}
return phone;
}
- (NSString *)dateStringFromToday:(NSDate *)date//(NSString *)dateStr;
{
/*NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"CST"]];
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
//NSDate *date = [dateFormat dateFromString:dateStr];
NSDateFormatter *dateFormat1 = [[NSDateFormatter alloc] init];
[dateFormat1 setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormat1 dateFromString:[dateFormat stringFromDate:dbDate]];*/
NSString *dateString;
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components, *components1;
// today time
components = [cal components:(NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components1 = [cal components:(NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:date];
NSDate *other = [cal dateFromComponents:components1];
if([today isEqualToDate:other]) {
NSDateFormatter *formate = [[NSDateFormatter alloc] init];
[formate setDateFormat:@"HH:mm"];
dateString = [formate stringFromDate:date];
return dateString;
} else if (components.day - 1 == components1.day) {
dateString = @"Yesterday";
return dateString;
}
// week time
components = [cal components:(NSWeekCalendarUnit) fromDate:[NSDate date]];
today = [cal dateFromComponents:components];
components1 = [cal components:(NSWeekCalendarUnit) fromDate:date];
other = [cal dateFromComponents:components1];
if(components.week == components1.week) {
NSDateFormatter *formate = [[NSDateFormatter alloc] init];
[formate setDateFormat:@"EEEE"];
dateString = [formate stringFromDate:date];
return dateString;
}
NSDateFormatter *formate = [[NSDateFormatter alloc] init];
[formate setDateFormat:@"dd/MM/yyyy"];
dateString = [formate stringFromDate:date];
return dateString;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _arrayDatas.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 64;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:@"AllTableView%ld:%ld", (long)indexPath.section, (long)indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSMutableDictionary *dict = [_arrayDatas objectAtIndex:(_arrayDatas.count - indexPath.row - 1)];
NSString *usersPhone = [[NSUserDefaults standardUserDefaults] objectForKey:USER_PREFIX];
if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Sent"] && [[dict objectForKey:LOC_PHONE] isEqualToString:usersPhone]) {
// sent cell
[[cell viewWithTag:0x100] removeFromSuperview];
// location field
cell.textLabel.text = [NSString stringWithFormat:@"To: %@", [dict objectForKey:LOC_TONAME]];
cell.textLabel.textColor = [UIColor colorWithRed:54.0/255.0 green:225.0/255.0 blue:250.0/255.0 alpha:1.0];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
// location name field
cell.detailTextLabel.text = [dict objectForKey:LOC_NAME];
cell.detailTextLabel.textColor = [UIColor lightGrayColor];
// date field
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(176, 0, 96, 64)];
NSString *string = [self dateStringFromToday:[dict objectForKey:LOC_TIME]];
label.text = string;
label.textColor = [UIColor lightGrayColor];
label.font = [UIFont systemFontOfSize:15];
label.textAlignment = NSTextAlignmentRight;
[label setTag:0x100];
[cell addSubview:label];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Sent"] && [[dict objectForKey:LOC_TOPHONE] isEqualToString:usersPhone]) {
// receive cell
[[cell viewWithTag:0x100] removeFromSuperview];
// location field
cell.textLabel.text = [NSString stringWithFormat:@"From: %@", [dict objectForKey:LOC_USER]];
cell.textLabel.textColor = [UIColor colorWithRed:155.0/255.0 green:205.0/255.0 blue:67.0/255.0 alpha:1.0];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
// location name field
cell.detailTextLabel.text = [dict objectForKey:LOC_NAME];
cell.detailTextLabel.textColor = [UIColor lightGrayColor];
// date field
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(176, 0, 96, 64)];
NSString *string = [self dateStringFromToday:[dict objectForKey:LOC_TIME]];
label.text = string;
label.textColor = [UIColor lightGrayColor];
label.font = [UIFont systemFontOfSize:15];
label.textAlignment = NSTextAlignmentRight;
[label setTag:0x100];
[cell addSubview:label];
if ([[dict objectForKey:LOC_ISOPEN] boolValue]) {
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mark_unread.png"]];
[imgView setFrame:CGRectMake(0, 0, 10, 10)];
cell.accessoryView = imgView;
}
} else if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Request"]) {
// request cell
[[cell viewWithTag:0x100] removeFromSuperview];
// location field
cell.textLabel.text = [NSString stringWithFormat:@"From: %@", [self getNameFromPhoneInFriends:[dict objectForKey:LOC_USER]]];
cell.textLabel.textColor = [UIColor colorWithRed:253.0/255.0 green:174.0/255.0 blue:55.0/255.0 alpha:1.0];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
// location name field
cell.detailTextLabel.text = @"";
//cell.detailTextLabel.text = [dict objectForKey:LOC_NAME];
//cell.detailTextLabel.textColor = [UIColor lightGrayColor];
// date field
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(176, 0, 96, 64)];
NSString *string = [self dateStringFromToday:[dict objectForKey:LOC_TIME]];
label.text = string;
label.textColor = [UIColor lightGrayColor];
label.font = [UIFont systemFontOfSize:15];
label.textAlignment = NSTextAlignmentRight;
[label setTag:0x100];
[cell addSubview:label];
// is opened
if ([[dict objectForKey:LOC_ISOPEN] boolValue]) {
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mark_unread.png"]];
[imgView setFrame:CGRectMake(0, 0, 10, 10)];
cell.accessoryView = imgView;
}
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//[self deselectRowAtIndexPath:indexPath animated:YES];
NSMutableDictionary *dict = [_arrayDatas objectAtIndex:(_arrayDatas.count - indexPath.row - 1)];
ShowWaitView1(YES, [self superview]);
[self setUserInteractionEnabled:NO];
// set mark to read to parse db
NSString *usersPhone = [[NSUserDefaults standardUserDefaults] objectForKey:USER_PREFIX];
if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Sent"] && [[dict objectForKey:LOC_PHONE] isEqualToString:usersPhone]) {
// sent cell
UIImage *img = nil;
if ([dict objectForKey:LOC_IMAGE]) {
img = [UIImage imageWithData:[dict objectForKey:LOC_IMAGE]];
}
ShowWaitView1(NO, [self superview]);
[self setUserInteractionEnabled:YES];
NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
[info setObject:dict[LOC_TONAME] forKey:LOC_USER];
[info setObject:dict[LOC_TOPHONE] forKey:LOC_PHONE];
[info setObject:dict[LOC_NAME] forKey:LOC_NAME];
[info setObject:dict[LOC_LAT] forKey:LOC_LAT];
[info setObject:dict[LOC_LONG] forKey:LOC_LONG];
[info setObject:dict[LOC_MSG] forKey:LOC_MSG];
[info setObject:dict[LOC_BARPOS] forKey:LOC_BARPOS];
//[info setObject:dict[LOC_TIME] forKey:LOC_TIME];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"CET"]];
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];
//object[PARSE_CALL_TIME] = [dateFormat stringFromDate:date];
NSString *string = [dateFormat stringFromDate:dict[LOC_TIME]];
[info setObject:string forKey:LOC_TIME];
if (dict[LOC_TRACKING]) {
[info setObject:dict[LOC_TRACKING] forKey:LOC_TRACKING];
}
if (dict[LOC_IMAGE]) {
[info setObject:dict[LOC_IMAGE] forKey:LOC_IMAGE];
}
[self.historyDelegate openSentLocation:[[dict objectForKey:LOC_LAT] doubleValue] lng:[[dict objectForKey:LOC_LONG] doubleValue] msg:[dict objectForKey:LOC_MSG] barpos:[[dict objectForKey:LOC_BARPOS] floatValue] image:img info:info];
} else if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Sent"] && [[dict objectForKey:LOC_TOPHONE] isEqualToString:usersPhone]) {
// received cell
// query request table
PFQuery *query = [PFQuery queryWithClassName:PARSE_TABLE_CALL];
[query whereKey:PARSE_CALL_TO equalTo:usersPhone];
[query whereKey:PARSE_CALL_STATUS equalTo:@"Sent"];
[query whereKey:PARSE_CALL_MODIFIED equalTo:[dict objectForKey:LOC_TIME]];
[query whereKey:PARSE_CALL_FROM equalTo:[dict objectForKey:LOC_PHONE]];
[query whereKey:PARSE_CALL_ISOPEN equalTo:[dict objectForKey:LOC_ISOPEN]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error && objects.count == 1) {
PFObject *obj = [objects firstObject];
obj[PARSE_CALL_ISOPEN] = @YES;
[obj saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
NSDate *dbDate = (NSDate *)[obj updatedAt];
[dict setObject:dbDate forKey:LOC_TRACKINGTIME];
NSArray *array = [[NSArray alloc] initWithObjects:dict, nil];
[self.historyDelegate replyLocationForRequest:array];
ShowWaitView1(NO, [self superview]);
[self setUserInteractionEnabled:YES];
}];
} else {
NSLog(@"WARNING: Receive query failed");
ShowWaitView1(NO, [self superview]);
[self setUserInteractionEnabled:YES];
}
}];
// set mark to read to local db
[dict setObject:@YES forKey:LOC_ISOPEN];
[_arrayDatas replaceObjectAtIndex:(_arrayDatas.count - indexPath.row - 1) withObject:dict];
[self reloadData];
} else if ([[dict objectForKey:PARSE_CALL_STATUS] isEqualToString:@"Request"]) {
// request cell
[dict setObject:[NSNumber numberWithBool:YES] forKey:LOC_ISOPEN];
NSMutableDictionary *sentDict = [[NSMutableDictionary alloc] init];
[sentDict setObject:dict[LOC_PHONE] forKey:LOC_PHONE];
[sentDict setObject:[self getNameFromPhoneInFriends:[dict objectForKey:LOC_USER]] forKey:LOC_USER];
//[self.historyDelegate replyLocationForRequest:array];
[self.historyDelegate sendLocationForRequest:@[sentDict]];
// save to parse opening information
NSString *usersPhone = [[NSUserDefaults standardUserDefaults] objectForKey:USER_PREFIX];
/*
NSString *strPre1 = [NSString stringWithFormat:@"%@ = '%@'", PARSE_CALL_TIME, dict[LOC_TIME]];
NSString *strPre2 = [NSString stringWithFormat:@"%@ = '%@'", PARSE_CALL_FROM, dict[LOC_USER]];
NSString *strPre3 = [NSString stringWithFormat:@"%@ = '%@'", PARSE_CALL_TO, usersPhone];
NSString *strPre4 = [NSString stringWithFormat:@"%@ = '%@'", PARSE_CALL_STATUS, @"Request"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:strPre1, strPre2, strPre3, strPre4];
PFQuery *query = [PFQuery queryWithClassName:PARSE_TABLE_CALL predicate:predicate];
*/
PFQuery *query = [PFQuery queryWithClassName:PARSE_TABLE_CALL];
[query whereKey:PARSE_CALL_TO equalTo:usersPhone];
[query whereKey:PARSE_CALL_STATUS equalTo:@"Request"];
[query whereKey:PARSE_CALL_MODIFIED equalTo:[dict objectForKey:LOC_TIME]];
[query whereKey:PARSE_CALL_FROM equalTo:[dict objectForKey:LOC_PHONE]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *obj in objects) {
obj[PARSE_CALL_ISOPEN] = @YES;
[obj saveInBackground];
}
ShowWaitView1(NO, [self superview]);
[self reloadData];
[self setUserInteractionEnabled:YES];
} else {
NSLog(@"WARNING: Request query failed");
ShowWaitView1(NO, [self superview]);
[self reloadData];
[self setUserInteractionEnabled:YES];
}
}];
// save to local db
[dict setObject:@YES forKey:LOC_ISOPEN];
[_arrayDatas replaceObjectAtIndex:(_arrayDatas.count - indexPath.row - 1) withObject:dict];
[self reloadData];
}
}
@end