2013-06-29 139 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]; 
} 

编辑

这是我的完整代码,对不起,我不明白所有这些,但我仍然很新。

.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

在你的numberOfRowsInSection中放置一个断点,看看它在哪里崩溃。另外,在这里发布你的@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

它确定。但是这听起来像是这个人刚刚熟悉了tableview,并且在行的单元格中没有超出范围的数组检查......所以简单的故障安全是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,你最有可能有一个编程错误。


此外,它看起来像你正在使用多个线程,读/写到相同的变量。没有在这些属性上实现某种线程安全性,这通常不是一个好主意。