2010-11-01 17 views
6

में अतिरिक्त अनुभाग जोड़ना मैं अपनी कंपनी के लिए एक छोटा आईफोन ऐप लिख रहा हूं जो एक समय में प्रत्येक कर्मचारी के लिए बुकिंग दिखाता है। मैं किसी दिए गए सप्ताह के लिए 'बुकिंग' की सूची प्राप्त करने के लिए कोर डेटा का उपयोग कर रहा हूं और सप्ताह के प्रति दिन एक अनुभाग में टूटा हुआ UITableView में उन्हें प्रदर्शित करना चाहता हूं।NSFetchedResultsController

समस्या यह है कि मुझे सप्ताह के प्रत्येक दिन के लिए 7 अनुभाग दिखाना होगा ('कोई बुकिंग' सेल दिखा रहा है जहां एक अनुभाग/दिनांक में कोई बुकिंग नहीं है)।

मैं अनुप्रयोग का स्क्रीनशॉट मिल गया है के रूप में यह खड़ा है here (खेद के रूप में मैं StackOverlow के लिए नया हूँ अभी तक छवियों पोस्ट नहीं कर सकते)

फिलहाल मैं एक 'fetchResults का उपयोग करके इस को प्राप्त करने कर रहा हूँ 'विधि है जो बुकिंग हो जाता है और उन्हें संभावित तारीखों की एक सरणी के लिए आयोजित करता है:

- (void)refetchResults {  

// Drop bookings Array, replacing with new empty one 
// 7 slots for 7 days each holding mutable array to recieve bookings where appropraite 
self.bookings = [NSArray arrayWithObjects:[NSMutableArray array], 
        [NSMutableArray array], [NSMutableArray array], 
        [NSMutableArray array], [NSMutableArray array], 
        [NSMutableArray array], [NSMutableArray array], nil]; 

// Create the fetch request for the entity. 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Booking" inManagedObjectContext:self.managedObjectContext]; 
[fetchRequest setEntity:entity]; 

// Limit to this weeks data 
[fetchRequest setPredicate: 
[NSPredicate predicateWithFormat:@"(date >= %@) && (date <= %@) && (resource == %@)", 
    firstDate,lastDate,resourceId]]; 

// Edit the sort key as appropriate. 
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES]; 
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"recId" ascending:YES]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, sortDescriptor2, nil]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

// Fetch records in to array 
NSError *error; 
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
if (results == nil) { 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 

[fetchRequest release]; 
[sortDescriptor release]; 
[sortDescriptor2 release]; 
[sortDescriptors release]; 

// Walk through records and place in bookings Array as required 
for (Booking *item in results) { 
    // Decide on array index by difference in firstDate and booking date 
    int idx = (int)[[item date] timeIntervalSinceDate:firstDate]/86400; 
    // Add the item to the approp MutArray 
    [(NSMutableArray *)[bookings objectAtIndex:idx] addObject:item]; 
} 

// Reload table 
[tableView reloadData]; 

}

मेरे सवाल यह है: वहाँ किसी भी तरह से NSFetchedResultsController का उपयोग कर एक ही परिणाम प्राप्त करने के लिए है? किसी भी तरह मुझे NSFetchedResultsController को 7 अनुभागों के लिए, सप्ताह के प्रत्येक दिन के लिए एक प्राप्त करने की आवश्यकता होगी, उनमें से कुछ में कोई बुकिंग नहीं होनी चाहिए।

किसी भी मदद की बहुत सराहना :)

उत्तर

2

मैं इतना उपयोग नहीं किया है, लेकिन आप NSFetchedResultsSectionInfo प्रोटोकॉल की जाँच हो सकता है। इसका उपयोग इस तरह किया जा सकता है, जाहिर है:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
NSInteger numberOfRows = 0; 
if ([[fetchedResultsController sections] count] > 0) 
    { 
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; 
    numberOfRows = [sectionInfo numberOfObjects]; 
    } 
return numberOfRows; 
} 

शुभकामनाएँ।

+0

उत्तर के लिए धन्यवाद

https://github.com/timothyarmes/TAFetchedResultsController

टिम: मैं इस मुद्दे को हल करने के लिए NSFetchedResultsController का एक उपवर्ग लिखा है। जब तक मुझे कुछ याद नहीं आ रहा है, मुझे अभी भी उपयुक्त अनुभाग खोजने के लिए मैपिंग अभ्यास करने की आवश्यकता है - यह है: तालिका दृश्य अनुभाग 0 से 6 के लिए पूछेगा (उदाहरण के लिए, 1 नवंबर से 7 नवंबर तक), लेकिन NSFetchedResultsController के पास केवल हो सकता है खंड 0, 1 और 2 (प्रतिनिधित्व, शायद, 2 नवंबर, 3 नवंबर और 6 नवंबर के लिए बुकिंग)। जब भी मैं NSFetchedResultsController का निर्माण करता हूं तो मैपिंग को कैश कर सकता हूं या जब भी मैं इसे करने के लिए एक अच्छा/साफ तरीका है, तो मैं मैपिंग को कैश कर सकता हूं। – Paul80nd

+0

आप सही हैं। खेद है कि अधिक मदद न करें। समय के साथ ही, मैं इसके साथ प्रयोग करूँगा। जानना उत्सुक है कि आप इसे कैसे हल करते हैं। – westsider

+0

दरअसल, इस बारे में थोड़ा और सोचते हुए मुझे लगता है कि इस पल के लिए एक उपयोग योग्य कामकाज सामान्य रूप से एक NSFetchedResultsController बनाना है, लेकिन उसके बाद उस सेट के अंत में 'मैपिंग' सरणी के फ़ील्ड अनुभागों में तालिकादृश्य के अनुभागों का अनुवाद करने के लिए NSFetchedResultsController का। इसका मतलब यह होना चाहिए कि मैं परिणाम नियंत्रक (जो अच्छा है;) से ऑब्जेक्ट नोटिफिकेशन प्राप्त कर सकता है - परिणामस्वरूप नियंत्रक से जोड़े गए/हटाए गए आइटमों के लिए सूचनाएं आने पर मुझे केवल 'मैपिंग' सरणी को अपडेट करने की आवश्यकता होगी। किसी भी तरह से, अगर मुझे एक अच्छा समाधान मिल जाए तो मैं इसे यहां पोस्ट करना सुनिश्चित कर दूंगा। – Paul80nd

7

तो, जैसा कि मौसम बाहर बहुत अच्छा नहीं है, मुझे अपने स्वयं के प्रश्न का उत्तर देने और westsider के जवाब में वर्णित 'कामकाज' को लागू करने के लिए जाना पड़ा है।

विचार 'मैपिंग' सरणी (केवल एक साधारण 7 स्लॉट int सरणी) को पकड़ना है जो तालिकादृश्य को अंतर्निहित fetchedresultscontroller अनुभाग के लिए पूछेगा अनुभाग को मैप करेगा। प्रत्येक सरणी स्लॉट में उचित सेक्शन इंडेक्स या '-1' होगा जहां कोई अंतर्निहित अनुभाग नहीं है (और जहां 'कोई बुकिंग' सेल इसके बजाए नहीं दिखाया जाना चाहिए)।

तो, मेरी refetchResults विधि हो जाता है:

- (void)refetchResults {  

    // Create the fetch request for the entity. 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Booking" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Limit to this weeks data 
    [fetchRequest setPredicate: 
    [NSPredicate predicateWithFormat:@"(date >= %@) && (date <= %@) && (resource == %@)", 
     firstDate,lastDate,resourceId]]; 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES]; 
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"recId" ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, sortDescriptor2, nil]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 

    // Set up FRC 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"date" cacheName:nil]; 
    self.fetchedResultsController = aFetchedResultsController; 
    self.fetchedResultsController.delegate = self; 
    [aFetchedResultsController release]; 
    [fetchRequest release]; 
    [sortDescriptor release]; 
    [sortDescriptor2 release]; 
    [sortDescriptors release]; 

    // Run up FRC 
    NSError *error = nil; 
    if (![fetchedResultsController_ performFetch:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    // Update FRC map 
    [self updateFRCMap]; 

    // Reload table 
    [tableView reloadData]; 
} 

मानचित्रण निम्न विधि में सेट है। इसे तब भी कहा जाता है जब मैपिंग को रीफ्रेश करने की आवश्यकता होती है - उदाहरण के लिए जब मुझे fetchedresultscontroller से कॉलबैक मिलते हैं जिन्हें जोड़ा/हटाया जाता है/आदि।

- (void)updateFRCMap { 

    // Set mapping table for seven days of week to appropriate section in frc 
    for (int idx=0;idx<7;idx++) { frcMap[idx] = -1; } // Reset mappings 
    // For each section 
    for (int sidx=0; sidx<[[self.fetchedResultsController sections] count]; sidx++) 
    { 
     // If section has items 
     if ([[[self.fetchedResultsController sections] objectAtIndex:sidx] numberOfObjects] > 0) 
     { 
      // Look at first booking of section to get date 
      NSDate *date = [(Booking *)[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:sidx]] date]; 
      // Decide on array index by difference in firstDate and booking date 
      int idx = (int)[date timeIntervalSinceDate:firstDate]/86400; 
      // Set map 
      frcMap[idx] = sidx; 
     } 
    } 
} 

यह शायद थोड़ा सा अनुकूलित किया जा सकता है लेकिन अभी के लिए ठीक काम करता है। मुझे संदेह है कि यह जीएमटी/बीएसटी घड़ी में परिवर्तन की समस्याएं पैदा कर सकता है जिसे फिक्सिंग की आवश्यकता होगी ... क्या घड़ी की समस्याएं इतनी जरूरी नहीं हैं कि ऐप्पल? ; P

उसके बाद यह सिर्फ tableview का उत्तर देते समय मानचित्रण सरणी का उपयोग करने का एक मामला है:

#pragma mark - 
#pragma mark Table view data source 

// Gets the booking from the fetchedResultsController using a remapped indexPath 
- (Booking *)bookingForMappedIndexPath:(NSIndexPath *)indexPath { 
    return (Booking *)[self.fetchedResultsController objectAtIndexPath: 
         [NSIndexPath indexPathForRow:indexPath.row inSection:frcMap[indexPath.section]]]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 7; // 7 days viewed 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 

    // Rows in section or 1 if no section 
    if (frcMap[section] != -1) { 
     id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:frcMap[section]]; 
     return [sectionInfo numberOfObjects]; 
    } else { 
     return 1; 
    } 

} 

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"RegularCell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell. 
    [self configureCell:cell atIndexPath:indexPath]; 
    return cell; 
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 

    // If no actual bookings for section then its a blank cell 
    if (frcMap[indexPath.section] == -1) { 

     // Configure a blank cell. 
     cell.textLabel.text = @"No Bookings"; 
     cell.detailTextLabel.text = @""; 

     cell.textLabel.font = [UIFont systemFontOfSize:16]; 
     cell.textLabel.textColor = [UIColor lightGrayColor]; 

     cell.accessoryType = UITableViewCellAccessoryNone; 
     cell.selectionStyle = UITableViewCellSelectionStyleNone; 

    } else { 

     // Regular cell 
     Booking *booking = [self bookingForMappedIndexPath:indexPath]; 
     cell.textLabel.text = booking.desc; 
     cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ %@", booking.location, booking.detail]; 

     cell.textLabel.font = [UIFont systemFontOfSize:14]; 
     cell.textLabel.textColor = [UIColor darkTextColor]; 
     cell.detailTextLabel.font = [UIFont systemFontOfSize:12]; 

     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
     cell.selectionStyle = UITableViewCellSelectionStyleBlue; 
    } 
} 

किसी भी टिप्पणी या लेखन के लिए बेहतर तरीके इस बहुत स्वागत :)

+0

इसके लिए धन्यवाद। मेरे पास एक ऐप में एक ही समस्या है जो मैं काम कर रहा हूं, "कल, आज, कल" प्रदर्शित करने की कोशिश कर रहा हूं-जो खाली हैं, उन अनुभागों में "इस दिन कुछ भी नहीं" सेल के साथ। मैंने इसे देखने से पहले वास्तव में एक ही समाधान के साथ चला गया। यह बुरा है कि FetchedResultsController के लिए इसका कोई समर्थन नहीं है ... – Accatyyc

1

मैं था कर रहे हैं यह समस्या भी है।

+0

कड़ी मेहनत की सराहना करें टिम, लेकिन आपके समाधान का एक ईमानदार प्रभाव यह है कि यह किसी मौजूदा प्रोजेक्ट में आसानी से नहीं छोड़ा जाता है। इसका समर्थन करने के लिए एक नई इकाई बनाना, और हटाना तर्क को संभालना, उससे अधिक काम है, इसलिए मुझे उम्मीद है कि "इस छोटे मुद्दे को बाईपास करें" –

संबंधित मुद्दे