0

I'm building an app that uses Parse as a web backend. I'm using this code but it tells me this when I run it:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

and

Warning: A long-running operation is being executed on the main thread. 

I've been researching but I can't come up with a solution

My code:

Header:

#import <Parse/Parse.h>

@interface HomeViewController : PFQueryTableViewController <UITableViewDataSource, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *storiesTableView;

@end

Implementation:

#import "HomeViewController.h"

@interface HomeViewController () {
// Declare variables
NSArray *_stories;
int itemsCount;
BOOL firstOpen;
}

@end

@implementation HomeViewController

- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {

    // The className to query on
    self.parseClassName = @"Story";

    // The key of the PFObject to display in the label of the default cell style
    self.textKey = @"objectId";

    // Whether the built-in pull-to-refresh is enabled
    self.pullToRefreshEnabled = YES;

    // Whether the built-in pagination is enabled
    self.paginationEnabled = NO;
}
return self;
}

- (PFQuery *)queryForTable
{
    PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];

    itemsCount = [query countObjects];

    return query;
}

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.

// Wise-verse.. but checks if this is the first open so that the user won
if (firstOpen == YES) {
    // Do nothing
} else {
    [self performSegueWithIdentifier:@"signInSegue" sender:self];
    firstOpen = YES;
}
}

-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
// Setup delegate and datasource
_storiesTableView.dataSource = self;
_storiesTableView.delegate = self;
}

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

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return itemsCount;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = @"cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

// Configure the cell
UILabel *nameLabel = (UILabel*) [cell viewWithTag:10];
nameLabel.text = [object objectForKey:@"objectId"];

UILabel *descriptionLabel = (UILabel*) [cell viewWithTag:20];
descriptionLabel.text = [object objectForKey:@"Story"];

return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Segue over to the viewing page
[self performSegueWithIdentifier:@"detailSegue" sender:self];
}

@end

My parse consists of these columns and there is current only one row there with this data on it:

  • objectId : UYpXIiQbPQ
  • createdAt : 2014-09-26T17:00:28.079Z
  • updatedAt : 2014-09-26T17:01:19.128Z
  • ACL : (undefined)
  • Story : "I woke up at 7 A.M monday morning. The dog was barking and the sky was open" (just a completely random test)
  • Author : Erik
  • Reviews (array) : (undefined)
  • Category (string) : Test Category

Can someone help with this?

----EDIT---- Stack trace:

    (lldb) bt
* thread #1: tid = 0xe3b1, 0x00000001947ac0a8 libobjc.A.dylib`objc_exception_throw, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001947ac0a8 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x00000001840abbec CoreFoundation`-[__NSArrayM objectAtIndex:] + 264
  * frame #2: 0x000000010012efdc iStory`-[PFQueryTableViewController tableView:cellForRowAtIndexPath:](self=0x000000014c613dc0, _cmd=<unavailable>, otherTableView=<unavailable>, indexPath=<unavailable>) + 196 at PFQueryTableViewController.m:307
    frame #3: 0x0000000188c3e39c UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 544
    frame #4: 0x0000000188c32fc4 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 2360
    frame #5: 0x0000000188a28c60 UIKit`-[UITableView layoutSubviews] + 172
    frame #6: 0x0000000188945874 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 572
    frame #7: 0x000000018829dd58 QuartzCore`-[CALayer layoutSublayers] + 168
    frame #8: 0x0000000188298944 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 320
    frame #9: 0x00000001882987e8 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32
    frame #10: 0x0000000188297fe8 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 276
    frame #11: 0x0000000188297d6c QuartzCore`CA::Transaction::commit() + 436
    frame #12: 0x000000018893c848 UIKit`_afterCACommitHandler + 156
    frame #13: 0x000000018417e388 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
    frame #14: 0x000000018417b314 CoreFoundation`__CFRunLoopDoObservers + 360
    frame #15: 0x000000018417b6f4 CoreFoundation`__CFRunLoopRun + 836
    frame #16: 0x00000001840a9664 CoreFoundation`CFRunLoopRunSpecific + 396
    frame #17: 0x000000018d1eb5a4 GraphicsServices`GSEventRunModal + 168
    frame #18: 0x00000001889ae4f8 UIKit`UIApplicationMain + 1488
    frame #19: 0x00000001000f541c iStory`main(argc=1, argv=0x000000016fd13a60) + 116 at main.m:14
    frame #20: 0x0000000194e1aa08 libdyld.dylib`start + 4

thanks a lot! Sincerely, Erik

rdelmar
  • 103,982
  • 12
  • 207
  • 218
Erik
  • 2,500
  • 6
  • 28
  • 49
  • Can you paste a stack trace into your question that shows the sequence of calls leading to the error? (Set a breakpoint on Objective-C exceptions if you haven't yet done that.) – Phillip Mills Sep 27 '14 at 16:34
  • @PhillipMills Sorry - but I don't completely understand what you're saying - how can I show the stack trace and where do you want me to put the breakpoint? – Erik Sep 27 '14 at 16:40
  • If you go to the breakpoint navigator in Xcode, you can click the plus sign at the bottom left and choose to add an exception breakpoint. That will stop (by default) when the exception is thrown. At that point you can type "bt" in the debug console at the (lldb) prompt to see the stack. – Phillip Mills Sep 27 '14 at 16:45
  • @PhillipMills oh I see, I pasted the stack trace now - learning something new every day ;) – Erik Sep 27 '14 at 16:50
  • The trace is saying that the error is inside `PFQueryTableViewController`. You probably need someone familiar with Parse to give you a good answer, but it's very likely to be a mismatch between `itemsCount` and whatever data Parse is using for your table cells. One left-field guess...what if you return `[[self objects] count]` as the `numberOfRowsInSection:` value. – Phillip Mills Sep 27 '14 at 17:02
  • @PhillipMills believe it or not, but the [[self objects] count] actually made the app work :) - Thanks! – Erik Sep 27 '14 at 17:15

3 Answers3

2
Warning: A long-running operation is being executed on the main thread

May be the result of running your PFQuery without a completion block. Parse provides a few options such as countObjectsInBackground.

philliping
  • 21
  • 2
0

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

Your first error says you are trying to get a value from an empty array. That may be because at this time you still don't have any value to use, as it's not yet completely downloaded from Parse and available. Try NSLog itensCount and also your Parse object key values inside queryForTable method to check if you are receiving any value before use then on your tableView.

Warning: A long-running operation is being executed on the main thread.

This is because you are doing synchronously networking, that may just freeze app screen but can also make it crash sometimes. You should always do asynchronously networking (using a background thread block) and Parse has it's own methods for it like findObjectsInBackgroundWithBlock (for query). Then you can feed your tableView just after actually receive the data. Check Parse docs for more info. https://www.parse.com/docs/ios_guide#queries/iOS Something like this:

[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

// if received successfully 
if (!error) {

// you have properly received objects so update your tableView with received data


}

else
{

// Log details of the failure
NSLog(@"Parse Error: %@ %@", error, [error userInfo]);

}
}

Hope it helps.

Marcos Reboucas
  • 3,409
  • 1
  • 29
  • 35