tldr: ImagedNamed ใช้ได้ จัดการกับหน่วยความจำได้ดี ใช้แล้วหมดกังวล
แก้ไขพฤศจิกายน 2012 : โปรดทราบว่าคำถามนี้เกิดจาก iOS 2.0! ข้อกำหนดด้านรูปภาพและการจัดการมีการเปลี่ยนแปลงมากมายตั้งแต่นั้นมา Retina ทำให้ภาพใหญ่ขึ้นและโหลดซับซ้อนขึ้นเล็กน้อย ด้วยการสนับสนุนในตัวสำหรับ iPad และภาพเรตินาคุณควรใช้ ImageNamed ในรหัสของคุณอย่างแน่นอน ตอนนี้เพื่อประโยชน์ของลูกหลาน:
ด้ายน้องสาวในฟอรั่มแอปเปิ้ลเดฟได้รับการจราจรที่ดีบางอย่าง โดยเฉพาะRincewind ได้เพิ่มอำนาจบางอย่าง
มีปัญหาใน iPhone OS 2.x ที่ imageNamed: แคชจะไม่ถูกล้างแม้ว่าจะมีคำเตือนหน่วยความจำก็ตาม ในเวลาเดียวกัน + imageNamed: มีการใช้งานจำนวนมากไม่ใช่สำหรับแคช แต่เพื่อความสะดวกซึ่งอาจขยายปัญหาได้มากกว่าที่ควรจะเป็น
ในขณะที่เตือนว่า
ในหน้าความเร็วมีความเข้าใจผิดทั่วไปเกี่ยวกับสิ่งที่เกิดขึ้น สิ่งที่ใหญ่ที่สุดที่ + imageNamed: ทำคือถอดรหัสข้อมูลรูปภาพจากไฟล์ต้นฉบับซึ่งมักจะขยายขนาดข้อมูลอย่างมีนัยสำคัญ (ตัวอย่างเช่นไฟล์ PNG ขนาดหน้าจออาจใช้ KB ไม่กี่โหลเมื่อบีบอัด แต่กินมากกว่าครึ่ง MB แตก - กว้าง * สูง * 4) โดย contrast + imageWithContentsOfFile: จะขยายขนาดภาพนั้นทุกครั้งที่ต้องการข้อมูลภาพ อย่างที่คุณสามารถจินตนาการได้ว่าหากคุณต้องการข้อมูลรูปภาพเพียงครั้งเดียวคุณจะไม่มีอะไรที่นี่นอกจากจะมีรูปภาพที่แคชไว้ห้อยอยู่รอบ ๆ และน่าจะนานกว่าที่คุณต้องการ อย่างไรก็ตามหากคุณมีภาพขนาดใหญ่ที่ต้องวาดใหม่บ่อยๆก็มีทางเลือกอื่นแม้ว่าสิ่งที่ฉันจะแนะนำเป็นหลักคือหลีกเลี่ยงการวาดภาพขนาดใหญ่นั้นใหม่ :)
ในส่วนที่เกี่ยวกับลักษณะการทำงานทั่วไปของแคชนั้นแคชจะขึ้นอยู่กับชื่อไฟล์ (ดังนั้นสองอินสแตนซ์ของ + imageNamed: ที่มีชื่อเดียวกันควรส่งผลให้มีการอ้างอิงถึงข้อมูลแคชเดียวกัน) และแคชจะเติบโตแบบไดนามิกเมื่อคุณขอรูปภาพเพิ่มเติมผ่าน + imageNamed :. ข้อผิดพลาดบน iPhone OS 2.xa ป้องกันไม่ให้แคชหดเมื่อได้รับคำเตือนเกี่ยวกับหน่วยความจำ
และ
ความเข้าใจของฉันคือ + imageNamed: cache ควรเป็นไปตามคำเตือนของหน่วยความจำบน iPhone OS 3.0 ทดสอบเมื่อคุณมีโอกาสและรายงานข้อบกพร่องหากคุณพบว่าไม่เป็นเช่นนั้น
คุณมีแล้ว imageNamed: จะไม่ทุบหน้าต่างของคุณหรือสังหารลูก ๆ ของคุณ มันค่อนข้างง่าย แต่เป็นเครื่องมือเพิ่มประสิทธิภาพ น่าเศร้าที่ชื่อไม่ดีและไม่มีความเท่าเทียมกันที่ใช้งานง่าย - ด้วยเหตุนี้ผู้คนจึงใช้มันมากเกินไปและอารมณ์เสียเมื่อมันทำงานได้ดี
ฉันเพิ่มหมวดหมู่ลงใน UIImage เพื่อแก้ไข:
// 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 ยังรวมโค้ดตัวอย่างไว้เพื่อสร้างเวอร์ชันที่ปรับให้เหมาะสมของคุณเอง ฉันไม่เห็นว่ามันคุ้มค่ากับการดูแล แต่นี่คือความสมบูรณ์
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);
ข้อเสียของรหัสนี้คือภาพที่ถอดรหัสใช้หน่วยความจำมากกว่า แต่การแสดงผลเร็วกว่า