I have a tableView which should load its cells with data from server.
When my data is loaded from server I call [self.tableView reloadData] inside completionhandler block.
So the method cellForRowAtIndexPath gets called again.
My implementation for cellForRowAtIndexPath is this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Configure the cell...
NewsCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"NewsCell" forIndexPath:indexPath];
if(!cell){
cell = [[NewsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"NewsCell"];
}
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
cell.newsTitle.text = currentNews.title;
// cell.newsTitle.text = #"salam";
return cell;
}
Note: self.newsList is an array that is populated with data from server
The code that parses response json from server is this:
[GNetworkHelper getJsonDataFromURL:urlString
withCompletionHandler:^(NSDictionary * jsonResponse) {
// Parse retrieved json and pass it to completion handler;;
NSMutableArray* news = [[NSMutableArray alloc] init];
if (jsonResponse) {
for (NSDictionary* new in jsonResponse) {
News *currentNew = [[News alloc] initWithDictionary:new];
[news addObject:currentNew];
}
}else{
News* testNew = [[News alloc] init];
[testNew setTitle:#"salam"];
[news addObject:testNew];
}
completionHandler(news);
}];
My problem: When I debug this code the cell variable I create using dequeueReusableCellWithIdentifier:forIndexPath function is null in the debugger's variables section, but when I use lldb command po to print it out I get this
(lldb) po cell
<NewsCell: 0x7fc5fadb2ee0; baseClass = UITableViewCell; frame = (0 0; 375 143); autoresize = W; layer = <CALayer: 0x7fc5fad9fcd0>>
The same happens for currentNews variable. For it I get this from po command
(lldb) po currentNews
<News: 0x7fc5fd0480d0>
I even can get properties on it like this:
(lldb) po currentNews.title
<__NSCFArray 0x7fc5fd047300>(
"some title"
)
There is no exception when stepping through this method's statements. But when the method returns the Unrecognized Selector exception is thrown
Why this happens??
The Strange thing is that if I change this line:
cell.newsTitle.text = currentNews.title;
to this:
cell.newsTitle.text = #"Some test text";
everything goes well, specifically the cell and currentNews variables are not null anymore and tableView renders the cells without any problem
The full stack trace is :
[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300
2015-09-16 11:30:40.630 Gallery[12013:952548] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300'
--- First throw call stack:
(
0 CoreFoundation 0x0000000105af3f35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010578cbb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000105afb04d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x0000000105a5327c ___forwarding___ + 988
4 CoreFoundation 0x0000000105a52e18 _CF_forwarding_prep_0 + 120
5 UIKit 0x00000001060a5f45 -[UILabel _textRectForBounds:limitedToNumberOfLines:includingShadow:] + 65
6 UIKit 0x00000001060a5da0 -[UILabel textRectForBounds:limitedToNumberOfLines:] + 76
7 UIKit 0x00000001060a9852 -[UILabel _intrinsicSizeWithinSize:] + 170
8 UIKit 0x00000001060a9932 -[UILabel intrinsicContentSize] + 76
9 UIKit 0x000000010655fea4 -[UIView(UIConstraintBasedLayout) _generateContentSizeConstraints] + 33
10 UIKit 0x000000010655fc64 -[UIView(UIConstraintBasedLayout) _updateContentSizeConstraints] + 422
11 UIKit 0x00000001065670d6 -[UIView(AdditionalLayoutSupport) updateConstraints] + 163
12 UIKit 0x00000001060a979d -[UILabel updateConstraints] + 272
13 UIKit 0x00000001065666fa -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 248
14 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
15 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
16 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
17 Foundation 0x0000000105332d6e -[NSISEngine withBehaviors:performModifications:] + 155
18 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
19 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
20 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
21 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
22 UIKit 0x0000000106566dbe __60-[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded]_block_invoke + 96
23 UIKit 0x0000000106566a86 -[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded] + 231
24 UIKit 0x000000010635c8b8 -[UITableViewCellContentView updateConstraintsIfNeeded] + 95
25 UIKit 0x000000010656719e -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeeded] + 159
26 UIKit 0x0000000105f4db2d -[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 114
27 UIKit 0x0000000105f59973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
28 QuartzCore 0x000000010504ade8 -[CALayer layoutSublayers] + 150
29 QuartzCore 0x000000010503fa0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
30 QuartzCore 0x000000010503f87e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
31 QuartzCore 0x0000000104fad63e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
32 QuartzCore 0x0000000104fae74a _ZN2CA11Transaction6commitEv + 390
33 QuartzCore 0x0000000104faedb5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
34 CoreFoundation 0x0000000105a28dc7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
35 CoreFoundation 0x0000000105a28d20 __CFRunLoopDoObservers + 368
36 CoreFoundation 0x0000000105a1eb53 __CFRunLoopRun + 1123
37 CoreFoundation 0x0000000105a1e486 CFRunLoopRunSpecific + 470
38 GraphicsServices 0x00000001085d29f0 GSEventRunModal + 161
39 UIKit 0x0000000105ee0420 UIApplicationMain + 1282
40 Gallery 0x000000010346ded3 main + 115
41 libdyld.dylib 0x0000000107325145 start + 1
42 ??? 0x0000000000000001 0x0 + 1
)
Can anybody tell me the reason for this?
The server JSON is an array of a string, ["some title"], and you expect it to be just a string "some title".
Try adding an assertion so that your parsing of the server data is correct.
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
NSAssert([currentNews.title isKindOfClass:[NSString class]],
#"Title is not a string but a %#.",
NSStringFromClass([currentNews.title class]));
cell.newsTitle.text = currentNews.title;
It simply indicates at some point when you try to access title value in currentNews object, it would be null. thats why your app throws exception. put a condition to check null value.
Use following method to check any value/object exist or not.
Usage
write following code in your cellForRowAtIndexPath method.
if([self isEmpty:currentNews.title])
{
cell.newsTitle.text = #"default value";
}
else
{
cell.newsTitle.text = currentNews.title[0];
}
// Method to check empty value/object
- (BOOL)isEmpty:(id)object
{
return object == nil
|| [object isKindOfClass:[NSNull class]]
|| ([object respondsToSelector:#selector(length)]
&& [(NSData *)object length] == 0)
|| ([object respondsToSelector:#selector(count)]
&& [(NSArray *)object count] == 0);
}
Related
I am trying to append the string of a Retweeted tweet in Objective-C however I am always getting an issue with certain types of tweets. I believe that there is something wrong in the way I am attempting to substring the tweets. My code is shown below
2015-08-20 15:40:20.699 Floadt[21417:932559] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString substringWithRange:]: Range {9223372036854775807, 52} out of bounds; string length 70'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cd58c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010c631bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010cd58b9d +[NSException raise:format:] + 205
3 CoreFoundation 0x000000010cc7fb98 -[__NSCFString substringWithRange:] + 136
4 Floadt 0x000000010929efa4 -[TwitterTableViewController tableView:cellForRowAtIndexPath:] + 2260
5 UIKit 0x000000010b465a28 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 508
6 UIKit 0x000000010b444248 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2853
7 UIKit 0x000000010b45a8a9 -[UITableView layoutSubviews] + 210
8 UIKit 0x000000010b3e4a2b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 536
9 QuartzCore 0x000000010b1a6ec2 -[CALayer layoutSublayers] + 146
10 QuartzCore 0x000000010b19b6d6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
11 QuartzCore 0x000000010b19b546 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
12 QuartzCore 0x000000010b107886 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
13 QuartzCore 0x000000010b108a3a _ZN2CA11Transaction6commitEv + 462
14 QuartzCore 0x000000010b1090eb _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
15 CoreFoundation 0x000000010cc8bca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
16 CoreFoundation 0x000000010cc8bc00 __CFRunLoopDoObservers + 368
17 CoreFoundation 0x000000010cc81a33 __CFRunLoopRun + 1123
18 CoreFoundation 0x000000010cc81366 CFRunLoopRunSpecific + 470
19 GraphicsServices 0x000000010eb09a3e GSEventRunModal + 161
20 UIKit 0x000000010b364900 UIApplicationMain + 1282
21 Floadt 0x000000010936574f main + 111
22 libdyld.dylib 0x000000010f32f145 start + 1
23 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is my code to Append the string:
if ([self Contains:#"RT" on:[data objectForKey:#"text"]]) {
TwitterRetweetCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"TwitterRetweetCell"];
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background.png"]];
if (cell == nil) {
cell = [[TwitterRetweetCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"TwitterRetweetCell"];
}
// Lookup RT User
NSString *text = [data objectForKey:#"text"];
NSRange start = [text rangeOfString:#"RT #"];
NSRange end = [text rangeOfString:#":"];
NSString *shortString = [text substringWithRange:NSMakeRange(start.location, end.location)];
NSString *evenShorterString = [shortString substringFromIndex:4];
[self lookupTwitterUser:evenShorterString];
//Set username for twitter
[cell.nameLabel setText:evenShorterString];
//Set Retweet Status
NSString *retName = [NSString stringWithFormat:#"Retweeted by %#",data[#"user"][#"screen_name"]];
[cell.retweetedLabel setText:retName];
//Set Profile Pic for Twitter
return cell;
}
The two ranges:
NSRange start = [text rangeOfString:#"RT #"];
NSRange end = [text rangeOfString:#":"];
You need to check that those substrings were actually found and only use the ranges if they were found. Otherwise the rest of your code will fail because the range's location will be NSNotFound, which is the large number in your crash log. That suggests that your code encountered text containing "RT" but not "RT #". You should perform the following check before attempting to use start and end:
if (start.location != NSNotFound && end.location != NSNotFound)
{
// use start and end
}
Or better still, use this if condition instead of if ([self Contains:#"RT" on:[data objectForKey:#"text"]]).
This is my code for loading data from sqlite file
- (void) loadInitialData{
// Form the query.
NSString *query = #"select * from tasklist";
// Get the results.
if (self.toDoItems != nil) {
self.toDoItems = nil;
}
NSArray *dbResultArray = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
//Logging for debug purpose
NSLog(#"Result set starts");
for(NSArray *subArray in dbResultArray) {
NSLog(#"Data in array: %#",subArray);
}
NSLog(#"Result set ends");
self.toDoItems = [[NSMutableArray alloc]initWithArray:dbResultArray];
// Reload the table view.
//[self.tblPeople reloadData];
[self.tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"todotaskdb.sql"];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
}
And I am getting this error using NSLog
2014-11-25 18:24:13.862 ToDoList[3213:60b] Result set ends
2014-11-25 18:24:13.865 ToDoList[3213:60b] -[__NSArrayM itemName]: unrecognized selector sent to instance 0x8c996f0
2014-11-25 18:24:13.900 ToDoList[3213:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM itemName]: unrecognized selector sent to instance 0x8c996f0'
*** First throw call stack:
(
0 CoreFoundation 0x018dc1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0165b8e5 objc_exception_throw + 44
2 CoreFoundation 0x01979243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x018cc50b ___forwarding___ + 1019
4 CoreFoundation 0x018cc0ee _CF_forwarding_prep_0 + 14
5 ToDoList 0x00004882 -[XYZToDoListTableViewController tableView:cellForRowAtIndexPath:] + 306
6 UIKit 0x0041411f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
7 UIKit 0x004141f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
8 UIKit 0x003f5ece -[UITableView _updateVisibleCellsNow:] + 2428
9 UIKit 0x0040a6a5 -[UITableView layoutSubviews] + 213
10 UIKit 0x0038a964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
11 libobjc.A.dylib 0x0166d82b -[NSObject performSelector:withObject:] + 70
12 QuartzCore 0x03d4745a -[CALayer layoutSublayers] + 148
13 QuartzCore 0x03d3b244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
14 QuartzCore 0x03d473a5 -[CALayer layoutIfNeeded] + 160
15 UIKit 0x0044cae3 -[UIViewController window:setupWithInterfaceOrientation:] + 304
16 UIKit 0x00362aa7 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212
17 UIKit 0x00361646 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
18 UIKit 0x00361518 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117
19 UIKit 0x003615a0 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67
20 UIKit 0x0036063a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120
21 UIKit 0x0036059c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400
22 UIKit 0x003612f3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870
23 UIKit 0x003648e6 -[UIWindow setDelegate:] + 449
24 UIKit 0x0043eb77 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180
25 UIKit 0x0035a474 -[UIWindow addRootViewControllerViewIfPossible] + 591
26 UIKit 0x0035a5ef -[UIWindow _setHidden:forced:] + 312
27 UIKit 0x0035a86b -[UIWindow _orderFrontWithoutMakingKey] + 49
28 UIKit 0x003653c8 -[UIWindow makeKeyAndVisible] + 65
29 UIKit 0x00315bc0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 2097
30 UIKit 0x0031a667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
31 UIKit 0x0032ef92 -[UIApplication handleEvent:withNewEvent:] + 3517
32 UIKit 0x0032f555 -[UIApplication sendEvent:] + 85
33 UIKit 0x0031c250 _UIApplicationHandleEvent + 683
34 GraphicsServices 0x038d1f02 _PurpleEventCallback + 776
35 GraphicsServices 0x038d1a0d PurpleEventCallback + 46
36 CoreFoundation 0x01857ca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
37 CoreFoundation 0x018579db __CFRunLoopDoSource1 + 523
38 CoreFoundation 0x0188268c __CFRunLoopRun + 2156
39 CoreFoundation 0x018819d3 CFRunLoopRunSpecific + 467
40 CoreFoundation 0x018817eb CFRunLoopRunInMode + 123
41 UIKit 0x00319d9c -[UIApplication _run] + 840
42 UIKit 0x0031bf9b UIApplicationMain + 1225
43 ToDoList 0x00004e0d main + 141
44 libdyld.dylib 0x01e25701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Ironically, if put below line at the end of viewDidLoad method, then it works.
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"todotaskdb.sql"];
Can anyone please tell me what is it that I am doing wrong?
Your toDoItems contains Arrays which contains your items! You're may be getting arrays of the single rows in your database, so you would have to fill them into single toDoItems objects first.
Maybe you could use a factory-like pattern with a method like popToDoItemFromRow:(NSArray *)row which returns your toDoItem for this row.
Then fill an new array in your for (NSArray *subArray in dbResultArray) for these single rows. This new array should you use in you cellForRow...
may be like..
- (void) loadInitialData{
// Form the query.
NSString *query = #"select * from tasklist";
// Get the results.
if (self.toDoItems != nil) {
self.toDoItems = nil;
}
NSArray *dbResultArray = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
if (self.toDoItems) {
[self.toDoItems removeAllObjects];
}
else {
self.toDoItems = [NSMutableArray new];
}
for(NSArray *subArray in dbResultArray) {
[self.toDoItems addObject:[ToDoItem popToDoItemFromRow:subArray]];
}
// Reload the table view.
//[self.tblPeople reloadData];
[self.tableView reloadData];
}
Im new to objective C and I was wondering if someone can help me figure out why my app keeps crashing. I believe it has something to do with my Array but I'm not sure how to fix it.. Can someone help please???..
Here's the Log output when it crashes:
2014-11-26 10:37:42.172 SamplePhotoReDo[89697:109203550] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010c75af35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010c09cbb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010c65301e -[__NSArrayI objectAtIndex:] + 190
3 UIKit 0x000000010d67474a -[UITableViewDataSource tableView:heightForHeaderInSection:] + 39
4 UIKit 0x000000010d221f4e -[UITableView _delegateWantsHeaderForSection:] + 261
5 UIKit 0x000000010d3a6983 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 162
6 UIKit 0x000000010d3ace45 -[UITableViewRowData rectForFooterInSection:heightCanBeGuessed:] + 320
7 UIKit 0x000000010d3acf3a -[UITableViewRowData heightForTable] + 56
8 UIKit 0x000000010d1ffaf0 -[UITableView _updateContentSize] + 381
9 UIKit 0x000000010d21cecd -[UITableView didMoveToWindow] + 65
10 UIKit 0x000000010d1a39a0 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1482
11 UIKit 0x000000010d1b4333 -[UIScrollView _didMoveFromWindow:toWindow:] + 55
12 UIKit 0x000000010d1a368e -[UIView(Internal) _didMoveFromWindow:toWindow:] + 696
13 UIKit 0x000000010d19c112 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 125
14 UIKit 0x000000010d19c086 -[UIView(Hierarchy) _postMovedFromSuperview:] + 437
15 UIKit 0x000000010d1a5f4b -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1604
16 UIKit 0x000000010d486534 -[UINavigationTransitionView transition:fromView:toView:] + 479
17 UIKit 0x000000010d2841ef -[UINavigationController _startTransition:fromViewController:toViewController:] + 2967
18 UIKit 0x000000010d284487 -[UINavigationController _startDeferredTransitionIfNeeded:] + 523
19 UIKit 0x000000010d284f47 -[UINavigationController __viewWillLayoutSubviews] + 43
20 UIKit 0x000000010d3ca509 -[UILayoutContainerView layoutSubviews] + 202
21 UIKit 0x000000010d1a8973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
22 QuartzCore 0x000000011052bde8 -[CALayer layoutSublayers] + 150
23 QuartzCore 0x0000000110520a0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
24 QuartzCore 0x000000011052087e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
25 QuartzCore 0x000000011048e63e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
26 QuartzCore 0x000000011048f74a _ZN2CA11Transaction6commitEv + 390
27 UIKit 0x000000010d12d54d -[UIApplication _reportMainSceneUpdateFinished:] + 44
28 UIKit 0x000000010d12e238 -[UIApplication _runWithMainScene:transitionContext:completion:] + 2642
29 UIKit 0x000000010d12cbf2 -[UIApplication workspaceDidEndTransaction:] + 179
30 FrontBoardServices 0x0000000112f002a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
31 CoreFoundation 0x000000010c69053c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
32 CoreFoundation 0x000000010c686285 __CFRunLoopDoBlocks + 341
33 CoreFoundation 0x000000010c686045 __CFRunLoopRun + 2389
34 CoreFoundation 0x000000010c685486 CFRunLoopRunSpecific + 470
35 UIKit 0x000000010d12c669 -[UIApplication _run] + 413
36 UIKit 0x000000010d12f420 UIApplicationMain + 1282
37 SamplePhotoReDo 0x000000010bb60453 main + 115
38 libdyld.dylib 0x000000010f2d2145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)'
Here's the code that might be causing the crash:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1 + self.collectionsFetchResults.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger numberOfRows = 0;
if (section == 0) {
numberOfRows = 1; // "All Photos" section
} else {
PHFetchResult *fetchResult = self.collectionsFetchResults[section - 1];
numberOfRows = fetchResult.count;
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
NSString *localizedTitle = nil;
if (indexPath.section == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:AllPhotosReuseIdentifier forIndexPath:indexPath];
localizedTitle = NSLocalizedString(#"All Photos", #"");
} else {
cell = [tableView dequeueReusableCellWithIdentifier:CollectionCellReuseIdentifier forIndexPath:indexPath];
PHFetchResult *fetchResult = self.collectionsFetchResults[indexPath.section - 1];
PHCollection *collection = fetchResult[indexPath.row];
localizedTitle = collection.localizedTitle;
}
cell.textLabel.text = localizedTitle;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *title = nil;
if (section > 0) {
title = self.collectionsLocalizedTitles[section - 1];
}
return title;
}
#pragma mark - PHPhotoLibraryChangeObserver
- (void)photoLibraryDidChange:(PHChange *)changeInstance
{
// Call might come on any background queue. Re-dispatch to the main queue to handle it.
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *updatedCollectionsFetchResults = nil;
for (PHFetchResult *collectionsFetchResult in self.collectionsFetchResults) {
PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:collectionsFetchResult];
if (changeDetails) {
if (!updatedCollectionsFetchResults) {
updatedCollectionsFetchResults = [self.collectionsFetchResults mutableCopy];
}
[updatedCollectionsFetchResults replaceObjectAtIndex:[self.collectionsFetchResults indexOfObject:collectionsFetchResult] withObject:[changeDetails fetchResultAfterChanges]];
}
}
if (updatedCollectionsFetchResults) {
self.collectionsFetchResults = updatedCollectionsFetchResults;
[self.tableView reloadData];
}
});
}
reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 0]'
Quite clear, your array doesn't have as many elements as you think it has. Put a break point at the places where your array is populated and double check it's as expected.
I have a NSDictionary that I add to a mutable array but when I try add the array to populate a uitableview I get an error.
NSMutableArray *array = [[NSMutableArray alloc] init];
for (id element in self.categoriesMutableNameArray) {
[array addObject:#"No"];
}
self.categoryDict = #{ #"title" : self.categoriesMutableNameArray, #"selected" : array};
self.categoryArr = [[NSMutableArray alloc] init];
self.categoryMutableDict = [NSMutableDictionary dictionaryWithDictionary:self.categoryDict];
[self.categoryArr addObject:self.categoryDict];
and the following categoryArr is printed like this:
2014-02-27 15:09:07.397 App[7982:70b] (
{
selected = (
No,
No,
No,
No,
No,
No,
No,
No,
No,
No,
No,
No,
No,
No
);
title = (
"Fashion - Women",
"Fashion - Men",
Kids,
"Accessories - Women",
"Accessories - Men",
"Styling / Hair",
Inspiration,
"Decoration / Architecture",
"Great Places",
"Art / Design",
"Music / Movie / Books",
"Food / Drink",
"Gadgets / Tech",
Rides
);
}
)
The trouble I am having is in the uitableview cellforrowatindexpath method I try and add the title key for the categoryArr to populate the uitableview and I get the following error on this line:
UILabel *categoryLabel = (UILabel *)[cell viewWithTag:111];
categoryLabel.text = [NSString stringWithFormat:#"%#",[[self.categoryArr objectAtIndex:indexPath.row] objectForKey:#"title"];
And the error log:
2014-02-27 15:24:33.804 App[8153:70b] -[__NSArrayM length]: unrecognized selector sent to instance 0xa9bc3a0
2014-02-27 15:24:33.807 App[8153:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM length]: unrecognized selector sent to instance 0xa9bc3a0'
*** First throw call stack:
(
0 CoreFoundation 0x020c75e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01e4a8b6 objc_exception_throw + 44
2 CoreFoundation 0x02164903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x020b790b ___forwarding___ + 1019
4 CoreFoundation 0x020b74ee _CF_forwarding_prep_0 + 14
5 Foundation 0x006e18ed -[NSConcreteMutableAttributedString replaceCharactersInRange:withString:] + 39
6 Foundation 0x006e255a -[NSConcreteMutableAttributedString initWithString:attributes:] + 293
7 UIKit 0x01172bc6 -[UILabel _setText:] + 97
8 UIKit 0x01172d84 -[UILabel setText:] + 40
9 App 0x00047ebd -[PiccImageCategoriesViewController tableView:cellForRowAtIndexPath:] + 1533
10 UIKit 0x010b461f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
11 UIKit 0x010b46f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
12 UIKit 0x01098774 -[UITableView _updateVisibleCellsNow:] + 2378
13 UIKit 0x010abe95 -[UITableView layoutSubviews] + 213
14 UIKit 0x01030267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
15 libobjc.A.dylib 0x01e5c81f -[NSObject performSelector:withObject:] + 70
16 QuartzCore 0x00c8e2ea -[CALayer layoutSublayers] + 148
17 QuartzCore 0x00c820d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
18 QuartzCore 0x00c81f40 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
19 QuartzCore 0x00be9ae6 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
20 QuartzCore 0x00beae71 _ZN2CA11Transaction6commitEv + 393
21 QuartzCore 0x00beb544 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
22 CoreFoundation 0x0208f4ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
23 CoreFoundation 0x0208f41f __CFRunLoopDoObservers + 399
24 CoreFoundation 0x0206d344 __CFRunLoopRun + 1076
25 CoreFoundation 0x0206cac3 CFRunLoopRunSpecific + 467
26 CoreFoundation 0x0206c8db CFRunLoopRunInMode + 123
27 GraphicsServices 0x027779e2 GSEventRunModal + 192
28 GraphicsServices 0x02777809 GSEventRun + 104
29 UIKit 0x00fc5d3b UIApplicationMain + 1225
30 App 0x0001406d main + 141
31 libdyld.dylib 0x02f4d70d start + 1
32 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Thanks
The return of [[self.categoryArr objectAtIndex:indexPath.row] objectForKey:#"title"]; is a array of NSString, categoryLabel.text = [NSString stringWithFormat:#"%#", /*the return array*/]; this is the problem.
Maybe what you want is:
NSArray *categoryDetailArr = [[self.categoryArr objectAtIndex:indexPath.section] objectForKey:#"title"];
categoryLabel.text = [[categoryDetailArr objectAtIndex:indexPath.row];
Write this code
categoryLabel.text = [[[self.categoryArr objectAtIndex:0] objectForKey:#"title"]objectAtIndex:indexPath.row];
instead OF
categoryLabel.text = [NSString stringWithFormat:#"%#",[[self.categoryArr objectAtIndex:indexPath.row] objectForKey:#"title"];
And plz check that in UITableView dataSource methods i.e
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [categoryLabel objectAtIndex:0]valueForKey:#"selected"].count;
}
OR
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [categoryLabel objectAtIndex:0]valueForKey:#"title"].count;
}
I have an iPhone app which fetches user information (first name, last name, city) in JSON format from different social networks.
This works mostly well, but one of the social networks returns the city as a number instead of a string (actually I should made one more REST call to map this number to a city name... but for now I just want to display the number).
And when I try to display that number in a UILabel I get the exception (here fullscreen):
2014-02-15 11:24:16.194 MyAuth[8872:a0b] -[__NSCFNumber length]: unrecognized selector sent to instance 0xb074f90
2014-02-15 11:24:16.203 MyAuth[8872:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0xb074f90'
*** First throw call stack:
(
0 CoreFoundation 0x01bb15e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x019348b6 objc_exception_throw + 44
2 CoreFoundation 0x01c4e903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x01ba190b ___forwarding___ + 1019
4 CoreFoundation 0x01ba14ee _CF_forwarding_prep_0 + 14
5 Foundation 0x015798ed -[NSConcreteMutableAttributedString replaceCharactersInRange:withString:] + 39
6 Foundation 0x0157a55a -[NSConcreteMutableAttributedString initWithString:attributes:] + 293
7 UIKit 0x0084fbc6 -[UILabel _setText:] + 97
8 UIKit 0x0084fd84 -[UILabel setText:] + 40
9 MyAuth 0x0000a296 -[UserViewController viewDidLoad] + 678
10 UIKit 0x007b6318 -[UIViewController loadViewIfRequired] + 696
11 UIKit 0x007b65b4 -[UIViewController view] + 35
12 UIKit 0x007d03e2 -[UINavigationController _startCustomTransition:] + 778
13 UIKit 0x007dd0c7 -[UINavigationController _startDeferredTransitionIfNeeded:] + 688
14 UIKit 0x007ddcb9 -[UINavigationController __viewWillLayoutSubviews] + 57
15 UIKit 0x00917181 -[UILayoutContainerView layoutSubviews] + 213
16 UIKit 0x0070d267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
17 libobjc.A.dylib 0x0194681f -[NSObject performSelector:withObject:] + 70
18 QuartzCore 0x054e12ea -[CALayer layoutSublayers] + 148
19 QuartzCore 0x054d50d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
20 QuartzCore 0x054d4f40 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
21 QuartzCore 0x0543cae6 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
22 QuartzCore 0x0543de71 _ZN2CA11Transaction6commitEv + 393
23 QuartzCore 0x0543e544 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
24 CoreFoundation 0x01b794ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
25 CoreFoundation 0x01b7941f __CFRunLoopDoObservers + 399
26 CoreFoundation 0x01b57344 __CFRunLoopRun + 1076
27 CoreFoundation 0x01b56ac3 CFRunLoopRunSpecific + 467
28 CoreFoundation 0x01b568db CFRunLoopRunInMode + 123
29 GraphicsServices 0x031a09e2 GSEventRunModal + 192
30 GraphicsServices 0x031a0809 GSEventRun + 104
31 UIKit 0x006a2d3b UIApplicationMain + 1225
32 MyAuth 0x0000ab7d main + 141
33 libdyld.dylib 0x02518725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
So I go to my JSON parsing code:
- (User*)createUserFromJson:(id)json
{
if (![json isKindOfClass:[NSDictionary class]]) {
NSLog(#"Parsing response failed");
return nil;
}
NSDictionary *dict = json[#"response"][0];
User *user = [[User alloc] init];
user.key = kVK;
user.userId = dict[#"uid"];
user.firstName = dict[#"first_name"];
user.lastName = dict[#"last_name"];
user.city = dict[#"city"]; // THE PROBLEMATIC LINE
user.avatar = dict[#"photo_big"];
user.female = (2 == [dict[#"female"] intValue]);
return user;
}
and try to change it to:
user.city = [NSString stringWithFormat:#"%d", dict[#"city"]];
but then I get the compile-time warning (here fullscreen):
Format specifies type 'int' but the argument has type 'id'
So my question is how to solve this issue cleanly (w/o Xcode warnings) and robust (when fetched JSON data happens to be a string)?
The fastest solution is:
[NSString stringWithFormat:#"%#", dict[#"city"]];
which will take the description of the string or the number and convert that into a string.
In the future you may want to use:
if ([1dict[#"city"] isKindOfClass:[NSNumber class]]) { ...
to check what you have received and work with it specifically. i.e. to do your lookup and to not use stringWithFormat: when you actually already have a string (because it's inefficient).