2013-10-25 25 views
20

Mam tablicę z zawartością. jak zwykle zawiera 20 obiektów. Chcę tej samej tablicy podzielić na 2 sekcje w Tableview. Próbuję wdrożyć go z NSMake w bieżącej tablicy. Na przykład potrzebuję dostać w pierwszym rzędzie sekcji 3 wierszy, a drugi zawiera całą resztę (17 wierszy).Jak utworzyć podbarwę NSArray za pomocą NSRange?

switch (section) { 
     case 0: 
      return 
      [[array subarrayWithRange:NSMakeRange(3, 8)] count]; 
      // in this line, it always takes from the first object in array, despite I told hime start from 3 (If I understand right, how to works NSMakeRange) 
      break; 
     case 1: 
      return 
      [[array subarrayWithRange:NSMakeRange(9, 19)] count]; 
      // here my app is crashing with an error 
      //*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray subarrayWithRange:]: range {9, 19} extends beyond bounds [0 .. 19]' 
     default: 
      break; 
    } 

Czy ktoś może mi w tym pomóc?

+4

Parametry NSMakeRange to (lokalizacja, długość). Być może myślisz, że to coś innego? –

+0

Jeśli masz zakodowany zakres, po co zawracać sobie głowę tworzeniem subarray? Wystarczy, że zwrócisz stałą liczbę dla każdej sekcji i unikniesz całego narzutu tworzenia 'NSRange' i zmarnowanego' NSArray'. – rmaddy

+0

@rmaddy Ja mniej więcej zadawałem to samo pytanie, powiedział, że chce rzeczywistych obiektów. –

Odpowiedz

53

NSMakeRange jest zdefiniowany jako (startingIndex, length), a nie (start, end), który wydaje się jak próbujesz go użyć.

Więc jeśli potrzebujesz pierwsze 3 obiekty, a następnie reszta będzie wyglądać następująco:

switch (section) { 
    case 0: 
     // This returns objects 0-2 in the array 
     return [array subarrayWithRange:NSMakeRange(0, 3)]; 
    case 1: 
     // This returns objects 3-20 in the array 
     return [array subarrayWithRange:NSMakeRange(3, 17)]; 
    default: 
     break; 
} 

Edit: Zgodnie z Twojego komentarza, jesteś rzeczywiście patrząc na licznik, aby powrócić w liczbie wierszy w Sekcja. Ponieważ używasz ustalonej liczby wierszy, możesz po prostu zwrócić rzeczywistą liczbę w instrukcji sprawy.

switch (section) { 
    case 0: 
     // This returns the count for objects 0-2 in the array 
     return 3; 
    case 1: 
     // This returns the count for objects 3-20 in the array 
     return 17; 
    default: 
     break; 
} 

rzeczywistości nie trzeba używać [subarrayWithRange], ani NSMakeRange. Jeśli musisz w pewnym momencie odwołać się do rzeczywistej tablicy, otrzymasz obiekt NSIndexPath, którego możesz użyć do pobrania obiektu z tablicy. Będziesz musiał użyć właściwości przekroju i wiersza.

Edit: NSRange ->NSMakeRange

+0

Cześć Joel, Więc jak mogę zrobić to, czego potrzebuję? Używam count, ponieważ potrzebuję return numberOfRowsInSection: – Anton

+0

@Anton zobacz moją zaktualizowaną odpowiedź. Zakłada to, że chcesz zwrócić tablicę. –

+0

w drugiej sesji zawsze pobiera wiersze od 0. Nie muszę zwracać liczby obiektów tablicy. sekcja 1 powinna zawierać obiekty od 1 do 3, a sekcja 2 powinna zawierać od 4 do 20. – Anton

5

Jak inni zauważyli używasz NSRange nieprawidłowo.

definicja Za to

typedef struct _NSRange { 
     NSUInteger location; 
     NSUInteger length; 
} NSRange; 

więc drugi parametr struct jest długość przedziale, nie położenie ostatniego elementu, jak pozornie wydaje.


To znaczy, że to, co robisz, jest znacznie bardziej skomplikowane, niż powinno być.

Jaki jest cel utworzenia podtablicy o znanej długości, a następnie zwrócenie długości samej subarray? Mając to na uwadze:

return [[array subarrayWithRange:NSMakeRange(3, 8)] count]; 

należy (za pomocą NSRange prawidłowo)

return [[array subarrayWithRange:NSMakeRange(3, 6)] count]; 

ale może faktycznie być tylko

return 6; 

lub jeśli długość zakres jest parametrem

return length; 

Ponownie, nie ma potrzebować w świecie, aby pokroić tablicę i policzyć. Długość jest znana a priori.


Więc w kontekście UITableViewDataSource, trzeba

  • zamian liczyć na każdej sekcji w -tableView:numberOfRowsInSection:. Coś jak

    switch(section) { 
        case 0: return 2; 
        case 1: return 18; 
    }  
    
  • zamian rzeczywiste obiekty w tableView:cellForRowAtIndexPath:. Coś jak

    id object = nil; 
    switch (indexPath.section) { 
        case 0: 
         object = self.objects[indexPath.row]; 
         break; 
        case 1: 
         object = self.objects[2 + indexPath.row]; 
         break; 
    } 
    ... 
    

Jako dodatkowy cynk, radziłbym stosując inny zapis na elemencie budowlanych

NSMakeRange(0, 42) 

można zapisać

(NSRange){ .location = 0, .length = 42 } 

który jest znacznie bardziej czytelny (i mniej podatny na błędy, zwłaszcza gdy jesteś w środku wątpliwości co do znaczenia parametrów).

Nawet

(NSRange){ 0, 42 } 

jest dopuszczalne. Myślę, że jest lepszy (i krótszy) niż NSMakeRange, ale traci korzyści lub czytelność.

1

Ok mam rozwiązać mój problem

W moim Fetcher klasie robiłam

_sectionOne = [news objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)]]; 
_sectionTwo = [news objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 17)]]; 

następnie

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 2; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    switch (section) { 
     case 0: 
      return [_sectionOne count]; 
      break; 
     case 1: 
      return [_sectionTwo count]; 
      break; 
     default: 
      break; 
    } 
    return 0; 
} 

następnie w metodzie cellForRowAtIndexPath:

switch (indexPath.section) { 
     case 0: 
      item = [_sectionOne objectAtIndex:indexPath.row]; 
      break; 
     case 1: 
      item = [_sectionTwo objectAtIndex:indexPath.row]; 
      break; 
     default: 
      break; 
    } 

pozycji - to mój NSObject z MVC

więc to działa jak chciałem :)

Dzięki za wszystko stara się mi pomóc.

Pozdrowienia