我遵循的一些经验法则:
使用弧
对 iboutlets(除了顶级示例:UIwindow)和委托使用 weak
对类属性使用 Strong,对 NSString 使用副本。
不要直接访问变量,使用 self....方式。
-
不要使用自动释放方式创建新对象,例如 NSArray *array = [NSArray arrayWithObjects.......,而是使用 NSArray *array = [NSArray alloc] initWit....
NSString 类的方法相同。尝试使用 [NSString alloc] initWithFormat..... 而不是 [NSString stringWithFormat.
当您添加 NSNotification(addObserver...) 中心时,必须在 dealloc 中删除(removeObserver..) 它们。
正确实施 didReceiveMemoryWarning(视图控制器级别)或 applicationDidReceiveMemoryWarning(应用程序级别,它比视图控制器级别首先调用),但有时您只希望从崩溃中保存。您可以显示提醒用户可用内存不足,您可以将 ..user 弹出/呈现到主屏幕。(不好的做法)。
在后台线程中时不要对主线程执行任何操作。始终对后台线程使用@autorelease 块。
对长时间运行的进程使用 GCD/NSOperation 队列。
密切关注您正在使用的图像资源,仅使用所需尺寸的图像,而不是根据需要将大图像缩放为小图像尺寸。
将自动释放池用于长时间运行的循环,这会创建大量自动释放对象。
我为你准备了一些代码 sn-p,ypu 可以遵循:
//way 1 all on main thread bad approach, basically we are just doing some image manipulation on main thread(should not do on main thread :))
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
YourApplicationDelegate *appDelegate = (YourApplicationDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate showLandscapeLoading];//think it as progress view/loader
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImagePNGRepresentation(pickedImage);
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"category_imagename.jpeg"];
NSError * error = nil;
//from here
[imageData writeToFile:path options:NSDataWritingAtomic error:&error];
**//the important part for discussion UI manipulation on main thread bad bad bad**
CGSize size1;//A
size1.width = 400;
size1.height = 400;
UIGraphicsBeginImageContext(size1);
[pickedImage drawInRect:CGRectMake(0, 0, size1.width, size1.height)];
UIImage *bigImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString *bigThumb = [documentsDirectory stringByAppendingPathComponent:@"category_thumb_imagename.jpeg"];
NSData *data1=UIImageJPEGRepresentation(bigImage, 0.5);
BOOL status1=[data1 writeToFile:bigThumb atomically:YES];
**//up to here should be in non ui thread/seperate thread**
**//below code should go in main thread**
NSLog(@"status1 -> %d",status1);
[self setCategoryImageName:bigImage];
[self.imgCategory setImage:pickedImage];
if (status1) {
isAddingCategoryImage = YES;
}
[appDelegate stopLandscapeLoading];
if (error != nil) {
NSLog(@"Error: %@", error);
return;
}
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:true];
}
[picker.view removeFromSuperview];
}
正确方法:
使用 NSOperation:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
YourApplicationDelegate *appDelegate = (YourApplicationDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate showLandscapeLoading];
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSError * error = nil;
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperationWithBlock:^
{
// Create a graphics image context very slow stuff
CGSize newSize = CGSizeMake(400, 400);
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[pickedImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
NSString *bigThumb = [documentsDirectory stringByAppendingPathComponent:@"category_thumb_imagename.jpeg"];
NSData *data1=UIImageJPEGRepresentation(newImage, 0.5);
BOOL status1=[data1 writeToFile:bigThumb atomically:YES];
// ok, now do UI stuff in the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[self setCategoryImageName:bigThumb];
[self.imgCategory setImage:pickedImage];
if (status1) {
isAddingCategoryImage = YES;
}
[appDelegate stopLandscapeLoading];
if (error != nil) {
NSLog(@"Error: %@", error);
return;
}
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:true];
}
[picker.view removeFromSuperview];
}];
}];
}
感谢和问候,
好了