tldr: ImagedNamed vẫn ổn. Nó xử lý bộ nhớ tốt. Sử dụng nó và ngừng lo lắng.
Chỉnh sửa tháng 11 năm 2012 : Lưu ý rằng câu hỏi này có từ iOS 2.0! Các yêu cầu về hình ảnh và xử lý đã thay đổi rất nhiều kể từ đó. Retina làm cho hình ảnh lớn hơn và tải chúng phức tạp hơn một chút. Với sự hỗ trợ tích hợp cho iPad và hình ảnh võng mạc, bạn chắc chắn nên sử dụng ImageNamed trong mã của mình. Bây giờ, vì lợi ích của hậu thế:
Các chủ đề chị em trên diễn đàn của Apple Dev nhận một số lưu lượng tốt hơn. Cụ thể Rincewind đã thêm một số quyền hạn.
Có một số vấn đề trong iPhone OS 2.x trong đó imageNamed: cache sẽ không được xóa, ngay cả sau khi có cảnh báo bộ nhớ. Đồng thời + imageNamed: đã được sử dụng rất nhiều không phải cho bộ nhớ cache, mà là vì sự tiện lợi, điều này có lẽ đã phóng đại vấn đề hơn mức đáng lẽ ra.
trong khi cảnh báo rằng
Về mặt tốc độ, có một sự hiểu lầm chung về những gì đang diễn ra. Điều lớn nhất mà + imageNamed: làm là giải mã dữ liệu hình ảnh từ tệp nguồn, điều này hầu như luôn làm tăng kích thước dữ liệu lên đáng kể (ví dụ: tệp PNG có kích thước màn hình có thể tiêu tốn vài chục KB khi nén, nhưng tiêu thụ hơn nửa MB giải nén - chiều rộng * chiều cao * 4). By Ngược + imageWithContentsOfFile: sẽ giải nén hình ảnh đó mỗi khi cần dữ liệu hình ảnh. Như bạn có thể tưởng tượng, nếu bạn chỉ cần dữ liệu hình ảnh một lần, bạn sẽ không giành được gì ở đây, ngoại trừ việc có một phiên bản hình ảnh được lưu trong bộ nhớ cache và có thể lâu hơn bạn cần. Tuy nhiên, nếu bạn có một hình ảnh lớn mà bạn cần phải vẽ lại thường xuyên, thì có những lựa chọn thay thế, mặc dù cách mà tôi muốn đề xuất chủ yếu là tránh vẽ lại hình ảnh lớn đó :).
Đối với hành vi chung của bộ nhớ cache, nó thực hiện bộ nhớ cache dựa trên tên tệp (vì vậy hai trường hợp + imageNamed: có cùng tên sẽ dẫn đến các tham chiếu đến cùng một dữ liệu được lưu trong bộ nhớ cache) và bộ nhớ cache sẽ phát triển động khi bạn yêu cầu thêm hình ảnh qua + imageNamed:. Trên iPhone OS, lỗi 2.xa ngăn bộ nhớ cache bị thu hẹp khi nhận được cảnh báo bộ nhớ.
và
Sự hiểu biết của tôi là bộ nhớ cache + imageNamed: nên tôn trọng cảnh báo bộ nhớ trên iPhone OS 3.0. Hãy kiểm tra nó khi bạn có cơ hội và báo cáo lỗi nếu bạn thấy không đúng như vậy.
Vì vậy, bạn có nó. imageNamed: sẽ không đập vỡ cửa sổ của bạn hoặc giết con bạn. Nó khá đơn giản nhưng nó là một công cụ tối ưu hóa. Đáng buồn thay, nó được đặt tên rất tệ và không có thứ tương đương nào dễ sử dụng - do đó mọi người lạm dụng nó và cảm thấy khó chịu khi nó chỉ thực hiện công việc của mình
Tôi đã thêm một danh mục vào UIImage để khắc phục điều đó:
// header omitted
// Before you waste time editing this, please remember that a semi colon at the end of a method definition is valid and a matter of style.
+ (UIImage*)imageFromMainBundleFile:(NSString*)aFileName; {
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", bundlePath,aFileName]];
}
Rincewind cũng bao gồm một số mã ví dụ để tạo phiên bản được tối ưu hóa của riêng bạn. Tôi không thể thấy nó là giá trị để bảo trì nhưng ở đây là cho sự hoàn chỉnh.
CGImageRef originalImage = uiImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
Đánh đổi với mã này là hình ảnh được giải mã sử dụng nhiều bộ nhớ hơn nhưng hiển thị nhanh hơn.