ส่วนข้อมูลหลัก NameKeyPath ที่มีปัญหาด้านประสิทธิภาพของแอตทริบิวต์ความสัมพันธ์

ฉันมี Core Data Model ที่มีสามเอนทิตี:
Person, Group, Photo ที่มีความสัมพันธ์ระหว่างกันดังนี้:

  • บุคคล ‹‹-----------> กลุ่ม (ความสัมพันธ์แบบหนึ่งต่อหลาย)
  • บุคคล ‹-------------> รูปถ่าย (ตัวต่อตัว)

เมื่อฉันทำการดึงข้อมูลโดยใช้ NSFetchedResultsController ใน UITableView ฉันต้องการจัดกลุ่มออบเจ็กต์ Person ในส่วนต่างๆ โดยใช้แอตทริบิวต์ name เอนทิตีของ Group

เพื่อสิ่งนั้น ฉันใช้ sectionNameKeyPath:@"group.name"

ปัญหาคือเมื่อฉันใช้แอตทริบิวต์จากความสัมพันธ์ Group NSFetchedResultsController จะดึงข้อมูลทุกอย่างล่วงหน้าเป็นชุดเล็กๆ 20 ชุด (ฉันมี setFetchBatchSize: 20) แทนที่จะดึงชุดข้อมูลในขณะที่ฉันเลื่อน tableView

หากฉันใช้แอตทริบิวต์จากเอนทิตี Person (เช่น sectionNameKeyPath:@"name") เพื่อสร้างส่วนต่างๆ ทุกอย่างทำงานได้ดี: NSFetchResultsController จะโหลดชุดเล็กๆ ของวัตถุ 20 รายการในขณะที่ฉันเลื่อน

รหัสที่ฉันใช้เพื่อสร้างอินสแตนซ์ NSFetchedResultsController:

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:[Person description]
                                              inManagedObjectContext:self.managedObjectContext];

    [fetchRequest setEntity:entity];

    // Specify how the fetched objects should be sorted
    NSSortDescriptor *groupSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"group.name"
                                                                        ascending:YES];

    NSSortDescriptor *personSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthName"
                                                                         ascending:YES
                                                                          selector:@selector(localizedStandardCompare:)];


    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:groupSortDescriptor, personSortDescriptor, nil]];

    [fetchRequest setRelationshipKeyPathsForPrefetching:@[@"group", @"photo"]];
    [fetchRequest setFetchBatchSize:20];

    NSError *error = nil;
    NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if (fetchedObjects == nil) {
        NSLog(@"Error Fetching: %@", error);
    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"group.name" cacheName:@"masterCache"];

    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

นี่คือสิ่งที่ฉันได้รับจากเครื่องมือหากฉันสร้างส่วนต่างๆ ตาม "group.name" โดยไม่มีการโต้ตอบใดๆ กับ UI ของแอป: Core Data Fetch with  ส่วนตามความสัมพันธ์

และนี่คือสิ่งที่ฉันได้รับ (ด้วยการเลื่อนเล็กน้อยบน UITableView) หาก SectionNameKeyPath เป็นศูนย์: Core Data Fetch โดยไม่มีส่วนใด ๆ

ได้โปรดใครสามารถช่วยฉันในเรื่องนี้ได้บ้าง?

แก้ไข 1:

ดูเหมือนว่าฉันได้รับผลลัพธ์ที่ไม่สอดคล้องกันจากโปรแกรมจำลองและเครื่องมือ: เมื่อฉันถามคำถามนี้ แอปจะเริ่มทำงานในโปรแกรมจำลองในเวลาประมาณ 10 วินาที (โดย Time Profiler) โดยใช้โค้ดด้านบน

แต่วันนี้ เมื่อใช้โค้ดเดียวกันกับข้างต้น แอปจะเริ่มทำงานในโปรแกรมจำลองใน 900 มิลลิวินาที แม้ว่าจะทำการดึงข้อมูลล่วงหน้าชั่วคราวสำหรับออบเจ็กต์ทั้งหมดและไม่ได้บล็อก UI ก็ตาม

ฉันได้แนบภาพหน้าจอใหม่บางส่วน: Time Profiler with Simulatorการดึงข้อมูลล่วงหน้าในโปรแกรมจำลองโดยไม่ต้องเลื่อน การดึงข้อมูลล่วงหน้าในโปรแกรมจำลองพร้อมการเลื่อน  และการดึงข้อมูลชุดเล็ก

แก้ไข 2: ฉันรีเซ็ตตัวจำลองและผลลัพธ์ก็น่าสนใจ: หลังจากดำเนินการนำเข้าและออกจากแอป การรันครั้งแรกจะมีลักษณะดังนี้: ทำงานครั้งแรกหลังจากรีเซ็ตตัวจำลองและนำเข้าใหม่ หลังจากการเลื่อนเล็กน้อย:   เรียกใช้ครั้งแรกหลังจากการรีเซ็ตตัวจำลอง การนำเข้าใหม่ และการเลื่อนบางส่วน ตอนนี้นี่คือสิ่งที่เกิดขึ้นในการเรียกใช้ครั้งที่สอง: การทำงานครั้งที่สองหลังจากนั้น  รีเซ็ตตัวจำลองและนำเข้าใหม่ หลังจากการรันครั้งที่ห้า: เรียกใช้ครั้งที่ห้า

แก้ไข 3: การรันแอปครั้งที่เจ็ดและแปดครั้ง ฉันได้รับสิ่งนี้: การรันครั้งที่เจ็ดวิ่งครั้งที่แปด


comment
ฉันเชื่อว่า Rick คนหนึ่งแนะนำลิงก์นี้ แต่คำตอบของเขา ได้รับการกลั่นกรอง ยังไงก็ตาม...ลองดูครับ เขาคิดว่ามันสามารถตอบคำถามของคุณได้   -  person staticVoidMan    schedule 31.08.2014
comment
คำถามที่เขียนดี   -  person Lorenzo B    schedule 14.09.2014
comment
@codeFi เป็นหนึ่งในข้อกังวลหลักของคุณที่นี่ว่าการดึงข้อมูลกำลังบล็อกการโต้ตอบของผู้ใช้หรือไม่   -  person quellish    schedule 15.09.2014
comment
@quellish ใช่ มันบล็อกการโต้ตอบของผู้ใช้เมื่อแอปเริ่มทำงาน เนื่องจากใช้เวลานานในการนำเสนอ UI แต่ปัญหานี้เกิดขึ้นเฉพาะในเครื่องจำลองเท่านั้น น่าแปลกที่เมื่อเรียกใช้แอปบน iPhone 4S แม้ว่าฉันจะดึงเอนทิตีทั้งกลุ่มและรูปภาพล่วงหน้า และใช้แอตทริบิวต์ชื่อของเอนทิตีกลุ่มเป็น SectionNameKeyPath แอปจะโหลดใน ~900ms   -  person Razvan    schedule 15.09.2014
comment
ฉันไม่รู้ว่าจะต้องทำอย่างไร...ในเครื่องจำลองฉันได้รับสิ่งหนึ่ง บนอุปกรณ์อีกสิ่งหนึ่ง...   -  person Razvan    schedule 15.09.2014
comment
หากคุณกำหนดเวลาโปรไฟล์ เวลาส่วนใหญ่เป็นการดึงข้อมูลหรืออย่างอื่น ไม่ใช่เรื่องแปลกที่การเพิ่มร้านค้าให้กับผู้ประสานงานร้านค้าแบบถาวรจะใช้เวลานาน   -  person quellish    schedule 15.09.2014
comment
@quellish ฉันได้แก้ไขโพสต์ของฉันด้วยข้อมูลใหม่   -  person Razvan    schedule 15.09.2014
comment
ในโปรไฟล์เวลา สลับโครงสร้างการเรียก ไม่แยกตามเธรด และแสดงการโทรยอดนิยม ควรทำให้ชัดเจนว่าเวลาถูกใช้ไปที่ใด   -  person quellish    schedule 15.09.2014
comment
@quellish ไม่มีประโยชน์ที่จะทำสิ่งนั้นในตอนนี้เพราะดูเหมือนว่าทุกอย่างจะโหลดเร็วมาก (690ms) แต่ถ้าคุณต้องการทราบว่าอะไรใช้เวลาในการคำนวณมากที่สุดในขณะนี้ __pread จาก libsystem_kernel.dylib (75ms)   -  person Razvan    schedule 15.09.2014
comment
@codeFi ในความคิดเห็นที่คุณบอกว่าดูเหมือนว่า Core Data ชอบที่จะเก็บนิ้วหัวแม่มือเป็นไบนารี่ในตารางฐานข้อมูลนั่นคือบนเครื่องจำลองหรืออุปกรณ์ ลักษณะการทำงานและประสิทธิภาพของการจัดเก็บบันทึกภายนอกอาจแตกต่างกันอย่างมากระหว่างเครื่องจำลองและอุปกรณ์   -  person quellish    schedule 16.09.2014
comment
@quellish สิ่งนี้เกิดขึ้นในเครื่องจำลอง ฉันไม่ได้ดูว่าเกิดอะไรขึ้นบนอุปกรณ์จากมุมมองนี้   -  person Razvan    schedule 16.09.2014
comment
เมื่อคุณระบุในโมเดลว่า Core Data สามารถใช้ที่จัดเก็บข้อมูลภายนอกสำหรับแอตทริบิวต์ที่เป็นโมเดลไบนารี Core Data จะตัดสินใจที่รันไทม์ว่าจะจัดเก็บข้อมูลไบนารีนั้นไว้ในที่จัดเก็บ SQLite หรือในไฟล์ภายนอก เหตุผลของ Core Data เกี่ยวกับสิ่งนั้นอาจแตกต่างกันเมื่อทำงานบนอุปกรณ์กับเครื่องจำลอง นอกจากนี้ การย้ายร้านค้าที่เขียนไฟล์บันทึกภายนอกอาจทำได้ มาก ช้า มีเหตุผลใดบ้างที่คิดว่าคุณกำลังดำเนินการย้ายข้อมูลบน Instruments run ในตำแหน่งที่คุณเห็นความล่าช้า   -  person quellish    schedule 16.09.2014
comment
ไม่ ฉันไม่ได้นำเข้าอะไรเลย การทดสอบที่ฉันทำกับฐานข้อมูลที่มีประชากรอยู่แล้ว   -  person Razvan    schedule 16.09.2014


คำตอบ (3)


นี่คือวัตถุประสงค์ที่ระบุไว้ของคุณ: ฉันต้องการให้ออบเจ็กต์ Person ถูกจัดกลุ่มเป็นส่วนต่างๆ ตามกลุ่มเอนทิตีความสัมพันธ์ แอตทริบิวต์ชื่อ และ NSFetchResultsController เพื่อดำเนินการดึงข้อมูลเป็นชุดเล็กๆ ขณะที่ฉันเลื่อนดู และไม่แสดงล่วงหน้าเหมือนที่กำลังทำอยู่ตอนนี้

คำตอบนั้นซับซ้อนเล็กน้อย เนื่องจากหลักๆ แล้ว NSFetchedResultsController สร้างส่วนต่างๆ อย่างไร และคำตอบนั้นส่งผลต่อพฤติกรรมการดึงข้อมูลอย่างไร

TL;DR; หากต้องการเปลี่ยนลักษณะการทำงานนี้ คุณจะต้องเปลี่ยนวิธีที่ NSFetchedResultsController สร้างส่วนต่างๆ

เกิดอะไรขึ้น?

เมื่อ NSFetchedResultsController ได้รับคำขอดึงข้อมูลโดยมีการแบ่งหน้า (fetchLimit และ/หรือ fetchBatchSize) มีหลายสิ่งที่เกิดขึ้น

หากไม่มีการระบุ sectionNameKeyPath แสดงว่าการดำเนินการเป็นไปตามที่คุณคาดหวังทุกประการ การดึงข้อมูลส่งคืนอาร์เรย์พร็อกซีของผลลัพธ์ โดยมีอ็อบเจ็กต์จริงสำหรับจำนวนรายการ fetchBathSize แรก ตัวอย่างเช่น ถ้าคุณมี setFetchBatchSize ถึง 2 และภาคแสดงของคุณตรงกับ 10 รายการในร้านค้า ผลลัพธ์จะมีอ็อบเจ็กต์สองรายการแรก ออบเจ็กต์อื่นๆ จะถูกดึงข้อมูลแยกกันเมื่อมีการเข้าถึง นี่เป็นประสบการณ์การตอบสนองแบบแบ่งหน้าได้อย่างราบรื่น

อย่างไรก็ตาม เมื่อมีการระบุ sectionNameKeyPath ตัวควบคุมผลลัพธ์ที่ดึงมาจะต้องดำเนินการเพิ่มเติมอีกเล็กน้อย ในการคำนวณส่วนต่างๆ จำเป็นต้องเข้าถึงเส้นทางคีย์นั้นบนออบเจ็กต์ทั้งหมดในผลลัพธ์ โดยระบุ 10 รายการในผลลัพธ์ในตัวอย่างของเรา สองอันแรกได้ถูกดึงไปแล้ว อีก 8 รายการจะถูกดึงออกมาในระหว่างการแจงนับเพื่อรับค่าเส้นทางคีย์ที่จำเป็นในการสร้างข้อมูลส่วน หากคุณมีผลลัพธ์จำนวนมากสำหรับคำขอดึงข้อมูล สิ่งนี้อาจไม่มีประสิทธิภาพมากนัก มีข้อบกพร่องสาธารณะหลายประการเกี่ยวกับฟังก์ชันการทำงานนี้:

NSFetchedResultsController ในตอนแรกใช้เวลานานเกินไปในการตั้งค่าส่วนต่างๆ

NSFetchedResultsController ละเว้นคุณสมบัติ fetchLimit

NSFetchedResultsController, Table Index และปัญหาประสิทธิภาพการดึงข้อมูลแบบแบตช์

... และอีกหลายคน เมื่อคุณคิดเกี่ยวกับเรื่องนี้มันก็สมเหตุสมผล ในการสร้างออบเจ็กต์ NSFetchedResultsSectionInfo ต้องใช้ตัวควบคุมผลลัพธ์ที่ดึงมาเพื่อดูทุกค่าในผลลัพธ์สำหรับ sectionNameKeyPath รวมเข้ากับการรวมค่าที่ไม่ซ้ำกัน และใช้ข้อมูลนั้นเพื่อสร้างจำนวนออบเจ็กต์ NSFetchedResultsSectionInfo ที่ถูกต้อง ตั้งชื่อและชื่อดัชนี รู้ว่าส่วนนั้นมีวัตถุจำนวนเท่าใดในผลลัพธ์ ฯลฯ ในการจัดการกับกรณีการใช้งานทั่วไป ไม่มีวิธีแก้ไขสิ่งนี้ ด้วยเหตุนี้ ร่องรอยเครื่องดนตรีของคุณจึงอาจดูสมเหตุสมผลกว่ามาก

คุณจะเปลี่ยนสิ่งนี้ได้อย่างไร?

คุณสามารถพยายามสร้าง NSFetchedResultsController ของคุณเองซึ่งมีกลยุทธ์ทางเลือกสำหรับการสร้างอ็อบเจ็กต์ NSFetchedResultsSectionInfo แต่คุณอาจพบปัญหาเดียวกันบางประการ ตัวอย่างเช่น หากคุณใช้ฟังก์ชัน fetchedObjects ที่มีอยู่เพื่อเข้าถึงสมาชิกของผลลัพธ์การดึงข้อมูล คุณจะพบกับลักษณะการทำงานเดียวกันเมื่อเข้าถึงอ็อบเจ็กต์ที่เป็นข้อบกพร่อง การใช้งานของคุณจะต้องมีกลยุทธ์ในการจัดการกับสิ่งนี้ (สามารถทำได้ แต่ขึ้นอยู่กับความต้องการและข้อกำหนดของคุณเป็นอย่างมาก)

โอ้พระเจ้า ไม่ แล้วการแฮ็กชั่วคราวบางประเภทที่ทำให้ทำงานได้ดีขึ้นเล็กน้อยแต่ไม่สามารถแก้ไขปัญหาได้ล่ะ

การเปลี่ยนแปลงโมเดลข้อมูลของคุณจะไม่เปลี่ยนพฤติกรรมข้างต้น แต่สามารถเปลี่ยนผลกระทบด้านประสิทธิภาพได้เล็กน้อย การอัปเดตเป็นกลุ่มจะไม่ส่งผลกระทบอย่างมีนัยสำคัญต่อลักษณะการทำงานนี้ และอันที่จริงแล้ว จะเล่นได้ไม่ดีนักกับตัวควบคุมผลลัพธ์ที่ดึงมา อย่างไรก็ตาม อาจมีประโยชน์มากกว่าสำหรับคุณหากตั้งค่า relationshipKeyPathsForPrefetching ให้รวมความสัมพันธ์กลุ่มของคุณแทน ซึ่งอาจปรับปรุงพฤติกรรมการดึงข้อมูลและข้อผิดพลาดได้อย่างมาก กลยุทธ์อื่นอาจเป็นการดึงข้อมูลอีกครั้งเพื่อแบทช์ข้อบกพร่องของออบเจ็กต์เหล่านี้ก่อนที่คุณจะพยายามใช้ตัวควบคุมผลลัพธ์ที่ดึงข้อมูล ซึ่งจะเติมแคชในหน่วยความจำ Core Data ระดับต่างๆ ในลักษณะที่มีประสิทธิภาพมากขึ้น

แคช NSFetchedResultsController ใช้สำหรับข้อมูลส่วนเป็นหลัก วิธีนี้จะป้องกันไม่ให้ส่วนต่างๆ ได้รับการคำนวณใหม่ทั้งหมดในแต่ละการเปลี่ยนแปลง (ในกรณีที่ดีที่สุด) แต่จริงๆ แล้วอาจทำให้การดึงข้อมูลเริ่มแรกเพื่อสร้างส่วนต่างๆ ใช้เวลานานกว่ามาก คุณจะต้องทดลองเพื่อดูว่าแคชนั้นคุ้มค่ากับกรณีการใช้งานของคุณหรือไม่

หากข้อกังวลหลักของคุณคือการดำเนินการข้อมูลหลักเหล่านี้กำลังบล็อกการโต้ตอบของผู้ใช้ คุณสามารถถ่ายโอนการดำเนินการเหล่านั้นจากเธรดหลักได้ NSFetchedResultsController สามารถใช้กับบริบทคิวส่วนตัว (พื้นหลัง) ได้ ซึ่งจะป้องกันไม่ให้การดำเนินการ Core Data ปิดกั้น UI

person quellish    schedule 15.09.2014
comment
คุณพลาดประเด็นของคำตอบของฉัน การอัปเดตแบตช์ใช้เพื่ออัปเดตแอตทริบิวต์ใหม่ (พูด groupName) บนเอนทิตี Person เมื่อ name ของ Group เปลี่ยนแปลง และสิ่งนี้ไม่เกี่ยวข้องกับ NSFethedResultsController แต่อย่างใด เกี่ยวกับสิ่งที่คุณพูดที่นี่: การเปลี่ยนแปลงโมเดลข้อมูลของคุณจะไม่เปลี่ยนพฤติกรรมข้างต้น แต่สามารถเปลี่ยนผลกระทบต่อประสิทธิภาพได้เล็กน้อย ฉันเดาว่ามันไม่ถูกต้อง แต่เพียงให้แน่ใจว่าฉันจะตั้งค่าตัวอย่างการส่งคืนพร้อมการทดสอบบางอย่าง - person Lorenzo B; 15.09.2014
comment
คำถามของผู้เขียนเกี่ยวกับประสิทธิภาพ NSFetchedResultsController เมื่อคำนวณส่วนต่างๆ เป็นครั้งแรก การอัปเดตเป็นกลุ่มไม่เกี่ยวข้องกับสิ่งนี้ และในสถานการณ์ทั่วไปอาจเป็นอันตรายได้ - การประสานการเปลี่ยนแปลงชุดงานด้วย NSFetchedResultsController นั้นไม่ใช่เรื่องเล็กน้อย พฤติกรรมที่ผู้เขียนอธิบายและกำลังมองหาคำแนะนำนั้นเป็นปัญหาเฉพาะถิ่นของวิธีที่ NSFetchedResultsController ต้องทำงานของมัน การทำให้โมเดลข้อมูลเป็นมาตรฐานจะไม่เปลี่ยนแปลงสิ่งนี้ เพียงแต่หมายความว่าจะต้องใช้ข้อมูลเพิ่มขึ้นเล็กน้อยเพื่อดูผลกระทบด้านประสิทธิภาพที่เท่าเดิม - อย่างดีที่สุด - person quellish; 15.09.2014
comment
@quellish จริง ๆ แล้ว flexadded นั้นถูกต้อง: เมื่อไม่กี่วันก่อนฉันได้ลองใช้แอตทริบิวต์ groupName บนเอนทิตี Person และสร้างส่วนจากมัน มันทำงานได้ตามที่คาดไว้: ไม่มีการดึงข้อมูลล่วงหน้าอีกต่อไป ออบเจ็กต์ Person ถูกจัดกลุ่มตาม groupName และ FetchController กำลังดึงข้อมูลเป็นชุดเล็กๆ ขณะที่ฉันเลื่อนดู อย่างไรก็ตาม จากมุมมองของฉัน วิธีการนี้เอาชนะจุดประสงค์ของการมีความสัมพันธ์ได้ - person Razvan; 15.09.2014

จากประสบการณ์ของฉัน วิธีที่จะบรรลุเป้าหมายของคุณคือการ ทำให้ปกติ โมเดลของคุณ โดยเฉพาะอย่างยิ่ง คุณสามารถเพิ่มแอตทริบิวต์ group ในเอนทิตี Person ของคุณ และใช้แอตทริบิวต์นั้นเป็น sectionNameKeyPath ดังนั้น เมื่อคุณสร้าง Person คุณควรส่งผ่านกลุ่มของกลุ่มนั้นด้วย

กระบวนการดีนอร์มัลไลเซชันนี้ถูกต้อง เนื่องจากช่วยให้คุณหลีกเลี่ยงการดึงออบเจ็กต์ Group ที่เกี่ยวข้องได้เนื่องจากไม่จำเป็น ข้อเสียอาจเป็นได้ว่าหากคุณเปลี่ยนชื่อกลุ่ม บุคคลทั้งหมดที่เกี่ยวข้องกับชื่อนั้นจะต้องเปลี่ยน ในทางกลับกัน คุณอาจมีค่าที่ไม่ถูกต้องได้

ประเด็นสำคัญที่นี่คือต่อไปนี้ คุณต้องจำไว้ว่า Core Data ไม่ใช่ฐานข้อมูลเชิงสัมพันธ์ โมเดลไม่ควรออกแบบเป็นสคีมาฐานข้อมูล ซึ่งอาจเกิดการนอร์มัลไลซ์ได้ แต่ควรออกแบบจากมุมมองของวิธีการนำเสนอและใช้ข้อมูลในส่วนติดต่อผู้ใช้

แก้ไข 1

ฉันไม่เข้าใจความคิดเห็นของคุณ คุณช่วยอธิบายให้ดีขึ้นได้ไหม

สิ่งที่ฉันพบว่าน่าสนใจมากคือแม้ว่าแอปจะดำเนินการดึงข้อมูลล่วงหน้าแบบเต็มในเครื่องจำลอง แอปจะโหลดใน 900ms (พร้อมวัตถุ 5,000 รายการ) บนอุปกรณ์ แม้ว่าเครื่องจำลองจะโหลดช้ากว่ามากก็ตาม

อย่างไรก็ตาม ฉันสนใจที่จะทราบรายละเอียดเกี่ยวกับเอนทิตี Photo ของคุณ หากคุณดึงภาพล่วงหน้า การดำเนินการโดยรวมอาจได้รับผลกระทบ

คุณจำเป็นต้องดึงข้อมูล Photo ล่วงหน้าภายในมุมมองตารางของคุณหรือไม่? มันเป็นนิ้วหัวแม่มือ (ภาพเล็ก ๆ )? หรือภาพปกติ? คุณใช้ประโยชน์จาก External Storage Flag หรือไม่

การเพิ่มแอตทริบิวต์เพิ่มเติม (เช่น group) ให้กับเอนทิตี Person อาจไม่มีปัญหา การอัปเดตค่าของแอตทริบิวต์นั้นเมื่อ name ของวัตถุ Group เปลี่ยนแปลง จะไม่เป็นปัญหาหากคุณดำเนินการในเบื้องหลัง นอกจากนี้ ตั้งแต่ iOS 8 เป็นต้นไป คุณจะมีการอัปเดตเป็นชุดตามที่อธิบายไว้ใน การอัปเดตชุดข้อมูลหลัก

person Lorenzo B    schedule 14.09.2014
comment
ขอบคุณสำหรับคำตอบที่เป็นประโยชน์ของคุณ ฉันกำลังคิดอย่างนั้น แต่อย่างที่คุณพูด ปัญหาเกิดขึ้นเมื่อฉันต้องการเปลี่ยนชื่อกลุ่มสำหรับวัตถุนับพันที่เกี่ยวข้องกับกลุ่มใดกลุ่มหนึ่ง สิ่งที่ฉันพบว่าน่าสนใจมากคือแม้ว่าแอปจะดำเนินการดึงข้อมูลล่วงหน้าแบบเต็มในเครื่องจำลอง แอปจะโหลดใน 900ms (พร้อมวัตถุ 5,000 รายการ) บนอุปกรณ์ แม้ว่าเครื่องจำลองจะโหลดช้ากว่ามากก็ตาม ฉันคิดว่ามีอย่างอื่นเกิดขึ้นบนอุปกรณ์... อุปกรณ์ที่เป็น iPhone 4S ที่ใช้ iOS 7 บิวด์ล่าสุด - person Razvan; 14.09.2014
comment
เกี่ยวกับวลีสุดท้ายของคุณ คุณพูดถูกจริงๆ! ฉันจะไม่นำเสนอออบเจ็กต์นับพันให้กับผู้ใช้โดยจัดกลุ่มตามส่วนต่างๆ ใน ​​tableview เดียว แต่ฉันจะมีมุมมองตารางที่มีเซลล์บางเซลล์ที่เป็นตัวแทนของกลุ่มและแยกจากแต่ละเซลล์ไปยังเนื้อหาของแต่ละกลุ่ม แต่นี่เป็นแบบฝึกหัดส่วนตัวสำหรับฉันที่จะทำความเข้าใจ Core Data และปัญหานี้ทำให้ฉันหงุดหงิดมาก - person Razvan; 15.09.2014
comment
เพิ่มคำแนะนำอื่น ๆ - person Lorenzo B; 15.09.2014
comment
ถึงผู้ลงคะแนนเสียงลงคะแนน ควรแทรกความคิดเห็นเกี่ยวกับ downvotes ด้วย - person Lorenzo B; 15.09.2014
comment
เป้าหมายที่ระบุไว้ของผู้เขียนคือ: ฉันต้องการให้วัตถุ Person ถูกจัดกลุ่มในส่วนต่างๆ ตามกลุ่มเอนทิตีความสัมพันธ์ แอตทริบิวต์ชื่อ และ NSFetchResultsController เพื่อทำการดึงข้อมูลเป็นชุดเล็กๆ ขณะที่ฉันเลื่อน และไม่แสดงล่วงหน้าเหมือนที่กำลังทำอยู่ตอนนี้ คำตอบของคุณไม่ได้กล่าวถึงเรื่องนี้ - person quellish; 15.09.2014
comment
@quellish การลดขนาดโมเดลสามารถปรับปรุงประสิทธิภาพการทำงานได้ หากคุณใส่แอตทริบิวต์ใหม่ เช่น groupName ในเอนทิตี Person คุณลักษณะนั้นสามารถใช้เพื่อจัดกลุ่มและเพื่อหลีกเลี่ยงการดึงข้อมูลล่วงหน้า - person Lorenzo B; 15.09.2014
comment
@flex ติดยาเสพติด การทำให้โมเดลไม่ปกติจะไม่เปลี่ยนพฤติกรรมการดึงข้อมูลเมื่อสร้างส่วนเริ่มต้น ซึ่งเป็นสิ่งที่ผู้เขียนขอคำแนะนำ การทำให้โมเดลเป็นปกติจะทำให้โมเดลใช้เวลาน้อยลงในการทำสิ่งที่ไม่ต้องการทำอยู่แล้ว หากคุณลดค่าศีลธรรมของตัวควบคุมผลลัพธ์ที่ดึงมาเพียงพอ บางทีนั่นอาจจะเปลี่ยนพฤติกรรมของมัน แต่อาจจะไม่ - person quellish; 15.09.2014
comment
@flexadded บนอุปกรณ์ แอปจะโหลดเร็วมาก (ใน 900ms) ในขณะที่โหลดในเครื่องจำลองในไม่กี่วินาที - person Razvan; 15.09.2014
comment
@flexadded เกี่ยวกับรูปภาพที่ฉันใช้แสดงใน tableview: เป็นภาพขนาดย่อขนาดเล็ก (5.000 จาก 48KB ต่อภาพ) และแอตทริบิวต์เปิดใช้งานตัวเลือก Allow External Storage แล้ว อย่างไรก็ตาม ดูเหมือนว่า Core Data ต้องการจัดเก็บ Thumbs เป็นไบนารี่ในตารางฐานข้อมูล เนื่องจากไฟล์ SQLite มีขนาดถึง ~130MB - person Razvan; 15.09.2014

หลังจากเกือบหนึ่งปีนับตั้งแต่ฉันโพสต์คำถามนี้ ในที่สุดฉันก็พบผู้ร้ายที่ทำให้เกิดพฤติกรรมนี้ (ซึ่งเปลี่ยนแปลงเล็กน้อยใน Xcode 6):

  1. เกี่ยวกับเวลาในการดึงข้อมูลที่ไม่สอดคล้องกัน: ฉันกำลังใช้แคช และในขณะนั้นฉันก็กลับไปกลับมาโดยเปิด ปิด และรีเซ็ตเครื่องจำลอง

  2. เกี่ยวกับความจริงที่ว่าทุกอย่างถูกดึงออกมาล่วงหน้าเป็นชุดเล็ก ๆ โดยไม่ต้องเลื่อน (ใน Core Data Instruments ของ Xcode 6 นั่นไม่ใช่กรณีอีกต่อไป - ตอนนี้เป็นการดึงข้อมูลครั้งใหญ่ครั้งใหญ่ซึ่งใช้เวลาทั้งวินาที):

ดูเหมือนว่า setFetchBatchSize ทำงานไม่ถูกต้องกับ parent/child contexts ปัญหานี้ได้รับการรายงานย้อนกลับไปในปี 2012 และดูเหมือนว่าจะยังคงมีอยู่ http://openradar.appspot.com/11235622< /ก>.

เพื่อแก้ไขปัญหานี้ ฉันได้สร้าง independent context อีกอันด้วย NSMainQueueConcurrencyType และตั้งค่า persistence coordinator ให้เหมือนกับที่ contexts อื่น ๆ ของฉันใช้อยู่

ข้อมูลเพิ่มเติมเกี่ยวกับปัญหา #2 ที่นี่: https://stackoverflow.com/a/11470560/1641848

person Razvan    schedule 28.07.2015