2013-06-29 3 views
0

У меня есть UITableView добавляет как подвид из self.view и он падает на

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

UITableView сбои

Вот мой код:

интерфейс (в CRFeedViewController.m)
@property (assign) BOOL dataIsLoaded;

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

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if(dataIsLoaded == YES) 
    { 
     return [self.items count]; 
    } 
    else { 
     return 1; 
    } 
} 

// Return a cell for the index path 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"cell"; 

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    // Cell label 
    cell.textLabel.text = @"Tweet"; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] init]; 
    } 

    return cell; 
} 

- (void)getTimeLine { 
    ACAccountStore *account = [[ACAccountStore alloc] init]; 
    ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]; 

    [account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) 
    { 
     if (granted == YES) 
     { 
      NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType]; 

      if ([arrayOfAccounts count] > 0) 
      { 
       ACAccount *twitterAccount = [arrayOfAccounts lastObject]; 

       NSURL *requestURL = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/home_timeline.json"]; 

       NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; 
       [parameters setObject:@"20" forKey:@"count"]; 
       [parameters setObject:@"1" forKey:@"include_entities"]; 

       SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:parameters]; 

       postRequest.account = twitterAccount; 

       [postRequest performRequestWithHandler: ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) 
        { 
         self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error]; 

         if (self.items.count != 0) { 
          dataIsLoaded = YES; 
          [self.tableView reloadData]; 
         } 
         else { 
          NSLog(@"No items"); 
         } 
        }]; 
      } 
     } else { 
      NSLog(@"No access"); 
     } 
    }]; 
} 

- (void) viewWillAppear:(BOOL)animated 
{ 
    [self getTimeLine]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    /** 
    * TABLE VIEW 
    * Add subview of the table 
    */ 
    self.items = [NSArray arrayWithObjects:@"test", nil]; 

    CGRect tableViewRect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); 
    UITableView *tableView = [[UITableView alloc] initWithFrame:tableViewRect style:UITableViewStylePlain]; 

    tableView.dataSource = self; 

    [self.view addSubview:tableView]; 
} 

EDIT

Вот мой полный код, извините, я все еще не понимаю, я все еще очень новый.

.h

// 
// CRFeedViewController.h 
// Twitter 
// 
// Created by Cody Robertson on 6/27/13. 
// Copyright (c) 2013 Cody Robertson. All rights reserved. 
// 

#import <UIKit/UIKit.h> 
#import <Accounts/Accounts.h> 
#import <Social/Social.h> 

@interface CRFeedViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> 

@property (strong, nonatomic) UITableView *tableView; 
@property (strong, nonatomic) NSArray *items; 

@end 

.m

// 
// CRFeedViewController.m 
// Twitter 
// 
// Created by Cody Robertson on 6/27/13. 
// Copyright (c) 2013 Cody Robertson. All rights reserved. 
// 

#import "CRFeedViewController.h" 

#import "CRComposeViewController.h" 
#import "CRSearchViewController.h" 

@interface CRFeedViewController() 

@property (assign) BOOL dataIsLoaded; 

- (void) composeTweet: (id) sender; 
- (void) searchTweets: (id) sender; 

- (void) getTimeLine; 

@end 

@implementation CRFeedViewController 

@synthesize dataIsLoaded; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     /** 
     * NAV BAR 
     * Add icon and button to nav bar 
     */ 

     // Add Twitter Icon as Title 
     UIImageView *UINavTitleLogo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UINavBarLogo.png"]]; 
     UINavTitleLogo.contentMode = UIViewContentModeScaleAspectFill; 
     self.navigationItem.titleView = UINavTitleLogo; 

     // Add Search & Compose Icon 
     UIImage *UISearchNavButton = [UIImage imageNamed:@"Search.png"]; 
     UIBarButtonItem *CRSearchNavButton = [[UIBarButtonItem alloc] initWithImage:UISearchNavButton style:UIBarButtonItemStylePlain target:self action:@selector(searchTweets:)]; 

     UIImage *UIComposeNavButton = [UIImage imageNamed:@"Compose.png"]; 
     UIBarButtonItem *CRComposeNavButton = [[UIBarButtonItem alloc] initWithImage:UIComposeNavButton style:UIBarButtonItemStylePlain target:self action:@selector(composeTweet:)]; 

     NSArray *UINavItems = @[CRComposeNavButton, CRSearchNavButton]; 
     self.navigationItem.rightBarButtonItems = UINavItems; 

     [[UINavigationBar appearance] setTitleTextAttributes:@{ 
      UITextAttributeTextColor: [UIColor whiteColor] 
     }]; 

     /** 
     * TAB BAR 
     * Add icon and label to task bar 
     */ 
     UIImage *CRFeedTabBarIcon = [UIImage imageNamed:@"Home.png"]; 
     UITabBarItem *CRFeedTabBarItem = [[UITabBarItem alloc] initWithTitle:@"Home" image:CRFeedTabBarIcon tag:0]; 
     self.tabBarItem = CRFeedTabBarItem; 
    } 
    return self; 
} 

- (void) composeTweet:(id)sender 
{ 
    /** 
    *  PUSH VIEW TO COMPOSE 
    *  Load the compose view 
    */ 
    CRComposeViewController *CRCompose = [[CRComposeViewController alloc] init]; 
    CRCompose.title = @"New Tweet"; 
    [self.navigationController pushViewController:CRCompose animated:YES]; 
} 

- (void) searchTweets:(id)sender 
{ 
    /** 
    *  PUSH VIEW TO SEARCH 
    *  Load the search view 
    */ 
    CRSearchViewController *CRSearch = [[CRSearchViewController alloc] init]; 
    CRSearch.title = @"Search"; 
    [self.navigationController pushViewController:CRSearch animated:YES]; 
} 

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

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    if(dataIsLoaded == YES) 
    { 
     return [self.items count]; 
    } 
    else { 
     return 1; 
    } 
} 

// Return a cell for the index path 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"cell"; 

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    // Cell label 
    cell.textLabel.text = @"Tweet"; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] init]; 
    } 

    return cell; 
} 

- (void)getTimeLine { 
    ACAccountStore *account = [[ACAccountStore alloc] init]; 
    ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]; 

    [account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) 
    { 
     if (granted == YES) 
     { 
      NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType]; 

      if ([arrayOfAccounts count] > 0) 
      { 
       ACAccount *twitterAccount = [arrayOfAccounts lastObject]; 

       NSURL *requestURL = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/home_timeline.json"]; 

       NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; 
       [parameters setObject:@"20" forKey:@"count"]; 
       [parameters setObject:@"1" forKey:@"include_entities"]; 

       SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:parameters]; 

       postRequest.account = twitterAccount; 

       [postRequest performRequestWithHandler: ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) 
        { 
         self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error]; 

         if (self.items.count != 0) { 
          dataIsLoaded = YES; 
          [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 
         } 
         else { 
          NSLog(@"No items"); 
         } 
        }]; 
      } 
     } else { 
      NSLog(@"No access"); 
     } 
    }]; 
} 

- (void) viewWillAppear:(BOOL)animated 
{ 
    [self getTimeLine]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    /** 
    * TABLE VIEW 
    * Add subview of the table 
    */ 
    self.items = [NSArray arrayWithObjects:@"test", nil]; 

    CGRect tableViewRect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); 
    UITableView *tableView = [[UITableView alloc] initWithFrame:tableViewRect style:UITableViewStylePlain]; 

    tableView.delegate = self; 
    tableView.dataSource = self; 

    [self.view addSubview:tableView]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 
+0

Определите элементы, пожалуйста. –

+0

@TBlue Пожалуйста, объясните .. –

+0

Если вы не можете определить предметы, то почему вы используете их в первую очередь? –

ответ

0

Добавить делегат первый так эти методы побежал. Не забудьте также подписаться на делегата в вашем .h.

ViewController.h

@interface ViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> 

@property (nonatomic, strong) NSArray *items; 

// В вашем viewDidLoad

tableView.dataSource = self; 
tableView.delegate = self; 
+0

Я их подписал в моем .h, и добавил это, и он все еще рушится при этом методе. –

+0

Поместите контрольную точку в свой номерOfRowsInSection и посмотрите, где она сбой. Кроме того, разместите свой @property для этого массива здесь. –

+0

Точка останова - это то, что внутри этого метода. В какой-то момент он разбился на 'return [self.items count]' теперь он сбой в 'if (dataIsLoaded == YES) {' –

0

Вы должны вызвать метод reloadData на главной теме:

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 

Не уверен, если это вызывает ваш сбой, но вам нужно инициализировать свои ячейки с помощью идентификатора повторного использования:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; 

Я бы порекомендовал вам опубликовать трассировку, зарегистрированную в Xcode при сбое приложения. Это даст лучшее представление о том, почему ваше приложение рушится.

0

Вы возвращаете 1 ячейку, даже если у вас нет данных. Вы должны вернуть 0

+2

Он отлично подходит для возврата 1, если данных нет. Например, вы можете показать строку «Загрузка ...». До тех пор, пока другие источники данных и методы делегирования данных обрабатывают дело должным образом, это нормально. – rmaddy

+0

Это нормально. Но похоже, что этот человек просто знаком с табличным представлением, и в ячейке для строки нет проверки вне границ. Таким образом, простой отказоустойчивый является 0 –

+0

За исключением текущего метода cellForRow ... просто создает пустую ячейку, поэтому нет никакой опасности. И, как утверждается, ошибка в методе 'numberOfRowsInSection ... '. Пока нам не сообщили о фактической ошибке, на этот вопрос нельзя ответить. – rmaddy

0

Если ошибка происходит в методе numberOfRows, то преступник, скорее всего:

[self.items count]; 

Наиболее вероятный случай это вызывает ошибку, если self.items не метод count. В вашем viewDidLoad вы установите его на NSArray, который имеет метод count. Тем не менее, есть одно место вы установите self.items:

self.items = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error]; 

В результате этого метода, скорее всего, не имеет метод count, и, следовательно, не является NSArray, но вы храните его в переменной, которая определяется как NSArray.

После этой линии, выше, поместите следующий код:

NSLog(@"Class: %@", NSStringFromClass([self.items class])); 

Если выход не NSArray, вы, скорее всего, ошибка программирования.


Кроме того, похоже, что вы используете несколько потоков для чтения/записи в одну и ту же переменную. Это, как правило, не очень хорошая идея, не прибегая к какой-либо безопасности потоков для этих свойств.