在按钮上点击大约60多次我的iPad应用程序变慢然后最终崩溃
开始我的应用程序正常工作,经过一段时间它变得缓慢而且更慢......
响应动作大约需要8到10秒,最后崩溃 我不知道为什么这一切都在发生。 我在uiviewcontroller上使用了collectionview,它的所有内容视图都是在custome cell class中创建的。
使用乐器在iPAd 2上进行测试后,进行了这些屏幕拍摄。
现在该怎么办?你有没有看到任何问题... ???
这里是UICollectionView Cell中的加号按钮执行操作,按钮点按时间随机增加,达到300000+ ms
注意--->主线程显示0.0 ms
这是什么意思...... ????
请指导我正确的方向
修改
这是我在按钮上点击这些方法的代码
// 'purchasedProduct' is NSMutuableDictionary
-(void)btnPlus:(id)sender event:(id)event
{
indexPaths = [[NSMutableArray alloc]init];
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:myCollection];
btnIndex = [myCollection indexPathForItemAtPoint: currentTouchPosition];
MyCell *cell = (MyCell*)[myCollection cellForItemAtIndexPath:btnIndex];
NSString *newCode = [productID objectAtIndex:btnIndex.row];
newQty = cell.cellQty.text;
newQty = [NSString stringWithFormat:@"%d",[newQty integerValue] + 1];
BOOL currentCellHasUpdates = purchasedProduct[newCode] != nil;
if (currentCellHasUpdates)
{
// Object Already Exist.......
[purchasedProduct setObject:newQty forKey:newCode];
prdID = newCode;
[self UpdateProduct];
}
else
{
// create new object........
[purchasedProduct setObject:newQty forKey:newCode];
prdID = newCode;
[self BuyProduct];
}
[indexPaths addObject:btnIndex];
[myCollection reloadItemsAtIndexPaths:indexPaths]; // I think problem is here.
}
CellForItemAtIndexPath方法是
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CellID" forIndexPath:indexPath];
[[cell cellBtnPlus] addTarget:self action:@selector( btnPlus:event:) forControlEvents:UIControlEventTouchUpInside];
[[cell cellBtnMinus] addTarget:self action:@selector(btnMinus:event:) forControlEvents:UIControlEventTouchUpInside];
BOOL currentCellHasUpdates = purchasedProduct[[productID objectAtIndex:indexPath.row]] != nil;
if (currentCellHasUpdates)
{
cell.cellQty.text = [purchasedProduct objectForKey: [productID objectAtIndex:indexPath.row]];
cell.cellQty.textColor = [UIColor blueColor];
}
else
{
cell.cellQty.textColor = [UIColor lightGrayColor];
cell.cellQty.text = @"0";
}
image = nil;
NSString *imageName =[[productID objectAtIndex:indexPath.row] stringByAppendingString:@".jpg"];
getImagePath = [documentsDirectory stringByAppendingPathComponent:imageName];
image = [UIImage imageWithData:[NSData dataWithContentsOfFile:getImagePath]];
if (image.size.width == image.size.height)
{
//set newSize
}
if (image.size.width < image.size.height)
{
//calculate newSize
}
else
{
//calculate newSize
}
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (image.size.width == image.size.height)
{
//set imgRect
}
if (image.size.width < image.size.height)
{
//Calculations for imgRect
}
if (image.size.width > image.size.height)
{
//Calculations for imgRect
}
cell.myImageView.frame = imgRect;
cell.myImageView.image = image;
cell.lbl1.text = [[desc objectAtIndex:indexPath.row] capitalizedString];
cell.lbl2.text = [@"Box Qty:" stringByAppendingString:[boxQty objectAtIndex:indexPath.row]];
cell.lbl4.text = [[code objectAtIndex:indexPath.row] uppercaseString];
cell.lbl5.text = [@"Pack Qty:" stringByAppendingString:[packQty objectAtIndex:indexPath.row]];
BOOL isStarProduct = starProducts[[productID objectAtIndex:indexPath.row]] != nil;
if (isStarProduct)
{
cell.lbl6.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"star.png"]];
}
else
{
cell.lbl6.backgroundColor = [UIColor clearColor];
}
return cell;
}
我认为问题是在CollectionView 中的特定索引路径上重新加载导致问题,因为它需要91%的时间来执行。我是对的.. ???
编辑2
-(void)BuyProduct
{
newDate = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
currentDate = [formatter stringFromDate:newDate];
database = [dBName UTF8String];
if (sqlite3_open(database, &dbConnection) == SQLITE_OK)
{
sqliteQuery = [NSString stringWithFormat:@"INSERT INTO ShopingCart"
" (fld1 , fld2, fld3, fld4, fld5, fld6, fld7, fld8, fld9, fld10, fld11, fld12, fld13, fld14, fld15, fld16)"
" VALUES (\'%d\', \"%@\", \'%d\', \"%@\", \"%@\", \"%@\", \"%f\", \"%f\", \"%@\", \"%@\","
" \"%@\", \"%f\", \"%.4f\", \'%d\', \'%d\', \'%d\')",
1,
currentDate,
91,
customerID,
[productID objectAtIndex:btnIndex.row],
[costPrice objectAtIndex:btnIndex.row],
[[price objectAtIndex:btnIndex.row] floatValue] * [newQty integerValue],
[[salePrice objectAtIndex:btnIndex.row] floatValue] * [newQty integerValue],
[qty objectAtIndex:btnIndex.row],
newQty,
[taxRate objectAtIndex:btnIndex.row],
[[price objectAtIndex:btnIndex.row] floatValue] * [newQty integerValue],
[[price objectAtIndex:btnIndex.row] floatValue] * [newQty integerValue] + [taxAmount floatValue],
0,
0,
0];
if (sqlite3_prepare_v2(dbConnection, [sqliteQuery UTF8String], -1, &sQLStatement, NULL) == SQLITE_OK)
{
if (sqlite3_step(sQLStatement) == SQLITE_DONE)
{
NSLog(@"Inserted into Shopping Cart");
}
sqlite3_finalize(sQLStatement);
}
sqliteQuery = [NSString stringWithFormat:@"SELECT SUM(NetPrice) As TotalAmount"
" FROM ShopingCart WHERE CustomerID = \'%@\'",customerID];
if (sqlite3_prepare_v2(dbConnection, [sqliteQuery UTF8String], -1, &sQLStatement, NULL) == SQLITE_OK)
{
if (sqlite3_step(sQLStatement) == SQLITE_ROW)
{
temp = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(sQLStatement, 0)];
}
sqlite3_finalize(sQLStatement);
}
ordAmount.text = [NSString stringWithFormat:@"Total £ %.2f",[temp floatValue]];
}
else
{
NSLog(@"Error %s ", sqlite3_errmsg(dbConnection));
}
sqlite3_close(dbConnection);
}
我应该/我可以在哪里改进我的代码?
答案 0 :(得分:3)
你的文书清楚地表明reloadItemsAtIndexPaths:
是经验不佳表现的罪魁祸首。这意味着集合视图需要很长时间才能使单元格出列。
看看你的cellForRowAtIndexPath:
方法,你的for循环似乎是一个有吸引力的赌注,因为你的表现会受到影响。对于每个单元格,您要迭代一系列希望满足以下条件的产品
if ([[productID objectAtIndex:indexPath.row] isEqualToString:[updatedCodes objectAtIndex:i]])
{
cell.cellQty.text = [updatedQty objectAtIndex:i];
cell.cellQty.textColor = [UIColor blueColor];
}
一旦这个条件成立,你就更新了单元格,但是你没有摆脱循环!
这意味着对于您遍历整个数组的每个单元格!你应该做的是在if中放置一个break语句来打破循环。
话虽如此,我认为我们可以变得更好。鉴于您有一个productID数组和一个updatedCodes数组,您真的应该考虑将这些与Dictionary相匹配。字典是通过特定键获取对象的好方法。可以将数组视为字典,其中键是数组索引。因此,当您在索引0处获取对象时,实际上是在获取其键为0的对象。因此,在您的示例中,productID自然可以是您的键,值将是产品。如果您知道相应的productID,这将允许您立即获取任何产品。
因此,您需要一本包含所有产品的字典。然后,您将需要一个包含所有更新代码的字典。您可以让集合视图显示字典中的所有产品(NSDictionary具有方法&#34; allValues&#34;)或者您可以拥有一系列产品。
所以你需要的基本想法是:
NSDictionary *productsKeyedByID = [NSDictionary dictionaryWitObjects:productsArray forKeys:[productsArray valueForKey:@"productID"]];\\where productID is a property on the product object
此方法背后的动机是允许您根据特定的产品ID快速访问产品或更新的产品。这意味着对于阵列中的每个产品,您都可以立即检查它是否存在于更新的产品词典中。
所以在你的cellForRowAtIndexPath中:你可以拥有
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CellID" forIndexPath:indexPath];
[[cell cellBtnPlus] addTarget:self action:@selector( btnPlus:event:) forControlEvents:UIControlEventTouchUpInside];
[[cell cellBtnMinus] addTarget:self action:@selector(btnMinus:event:) forControlEvents:UIControlEventTouchUpInside];
NSString *currentCellProductId = productsArray[indexPath.row];
//using the modern syntax - you could also use the objectForKey: method.
BOOL currentCellHasUpdates = updatedCodesKeyedByID[currentCellProductId] != nil;
if (currentCellHasUpdates) {
cell.cellQty.text = updatedCodesKeyedByID[currentCellProductId].quantity;
cell.cellQty.textColor = [UIColor blueColor];
} else {
cell.cellQty.textColor = [UIColor lightGrayColor];
cell.cellQty.text = @"0";
}
现在,在处理按钮时,您还可以利用词典的强大功能:
-(void)btnPlus:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:myCollection];
btnIndex = [myCollection indexPathForItemAtPoint: currentTouchPosition];
MyCell *cell = (MyCell*)[myCollection cellForItemAtIndexPath:btnIndex];
NSString *newCode = [productID objectAtIndex:btnIndex.row];
newQty = cell.cellQty.text;
if (updatedCodesKeyedByID[newCode] != nil)
{
//NSLog(@"Object Already Exist...");
id codeToUpdate = updatedCodesKeyedByID[newCode];
codeToUpdate.quantity++;
[self UpdateProduct]; // Open DB SQlite DB Connection and update Table Record and Close Connection.
}
else
{
updatedCodesKeyedByID[newCode] = //create new object
[self BuyProduct]; // Open DB SQlite DB Connection and update Table Record and Close Connection.
}
}
注意您可能需要考虑将设计更改为只有一个包含产品的词典,并且每个产品都有关联的数量。未设置时,默认为0。这样你只需要检查一个词典就可以完成你在这篇文章中所做的事情。即更新项目的数量。
在将此讨论转移到聊天之后,编辑,最后一个难题是调用UICollectionView的reloadItemsAtIndexPaths:在performBatchUpdates块中。