Crash while setting completion handler for TWTweetComposeViewController - iphone

Okay this is the first place in my app I'm using a block for anything so is there some setup or Xcode setting I need to check? This seems to me a simple use of blocks, not doing anything fancy but it crashes out on: tweetViewController.completionHandler = ^(TWTweetComposeViewControllerResult result) in the iOS 6 simulator.
- (void) showTweetComposer
{
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
[self presentViewController:tweetViewController animated:YES completion:nil];
tweetViewController.completionHandler = ^(TWTweetComposeViewControllerResult result)
{
[self dismissModalViewControllerAnimated:YES];
};
[tweetViewController release];
}
thread #1: tid = 0x1c03, 0x02e3d09f libobjc.A.dylib`objc_msgSend + 19, stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
frame #0: 0x02e3d09f libobjc.A.dylib`objc_msgSend + 19
frame #1: 0x02e28cc9 libobjc.A.dylib`objc_setProperty_nonatomic_copy + 49
frame #2: 0x051c38b2 Social`-[SLTwitterComposeViewController setCompletionHandler:] + 47
frame #3: 0x001e2e06 MyApp`-[SocialViewController showTweetComposer] + 246 at SocialViewController.m:137
frame #4: 0x001e2ff7 MyApp`-[SocialViewController tweetToFriendsRowTouched] + 247 at SocialViewController.m:150
frame #5: 0x02e3f663 libobjc.A.dylib`-[NSObject performSelector:] + 62
frame #6: 0x0018b4f1 MyApp`-[GroupedTableViewController tableView:didSelectRowAtIndexPath:] + 401 at GroupedTableViewController.m:143
This happens whether I'm logged into twitter or not.
EDIT: I added a simple block based code snippet to the beginning for my showTweetComposer method to test that any kind of blocks are working in my code:
[UIView animateWithDuration:0.2 animations:^{
self.view.alpha = 0.0;
} completion:^(BOOL finished){
[self.view removeFromSuperview];
}];
Now it is crashing on this new block. So, it would seem there's something in my project that needs to be set to support using blocks but I'm not sure what that would be. My iOS deployment target is set to iOS 4.3.

Okay, solved. This gist is, don't weak-link against libSystem.dylib using -weak_library
Found the answer here

Related

Adding MKPolyline Overlay to MKMapView crashes application

My application was working fine on iOS6 but it is crashing on iOS 7 due to bad access when I add overlay to MKMapView.My code is as follows
MKPolyline *polyline = [[MKPolyline alloc] init];
polyline = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[directionMap addOverlay:polyline];
This is the crash log
(lldb) bt
*
thread #51: tid = 0x1cc5, 0x38755f8c libdispatch.dylib`dispatch_retain$VARIANT$mp + 8, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
frame #0: 0x38755f8c libdispatch.dylib`dispatch_retain$VARIANT$mp + 8
frame #1: 0x3598dbc8 VectorKit`-[VKRasterOverlayTileSource init] + 176
frame #2: 0x358cfd24 VectorKit`-[VKMapModel _rasterOverlayTileSourceForLevel:] + 308
frame #3: 0x358d0226 VectorKit`-[VKMapModel addRasterOverlay:] + 46
frame #4: 0x2f068dfe MapKit`-[MKOverlayContainerView _insertDrawable:forOverlay:atIndex:level:] + 1010
frame #5: 0x2f06752e MapKit`-[MKOverlayContainerView _configureAndAddDrawable:forOverlay:level:] + 326
frame #6: 0x2f0676ac MapKit`-[MKOverlayContainerView _considerAddingDrawable:inAddRect:level:] + 372
frame #7: 0x2f067cce MapKit`-[MKOverlayContainerView addOverlay:level:] + 246
frame #8: 0x001394c8 Falcon`-[GetDirectionVC showRouteFrom:to:](self=0x19742820, _cmd=0x001fa466, f=CLLocationCoordinate2D at 0x04f9ec2c, t=CLLocationCoordinate2D at 0x04f9ec1c) + 956 at GetDirectionVC.m:226
frame #9: 0x001390ee Falcon`-[GetDirectionVC loadLocations](self=0x19742820, _cmd=0x001fa458) + 1314 at GetDirectionVC.m:173
frame #10: 0x2e876e26 Foundation`__NSThread__main__ + 1062
frame #11: 0x38891c1c libsystem_pthread.dylib`_pthread_body + 140
frame #12: 0x38891b8e libsystem_pthread.dylib`_pthread_start + 102
(lldb)
I had the same problem, the stack trace looks misleading to me. My bugfix is to explicitely add the overlay on the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
[mapView addOverlay:myRouteLine];
});
or if you'd like to use the new MKOverlayRenderer:
dispatch_async(dispatch_get_main_queue(), ^{
[mapView addOverlay:myRouteLine level:MKOverlayLevelAboveRoads];
});
In my case, I'm downloading asynchronously some data, generate Polylines, create MKOverlayViews / MKOverlayRenderes (didn't help to replace the deprecated code) and add the overlay to the map.
Use following If you are creating poly lines in thread other than main thread:
[self performSelectorOnMainThread:#selector(addPolyLineToMap:) withObject:polyline waitUntilDone:NO];
-(void)addPolyLineToMap:(MKPolyline*)apolyline{
[mapview addOverlay:apolyline];
}

iDevice camera shows black instead of preview

I am developing an app that captures images from iDevice's camera and upload it to web service.
NO problem everything is working fine except the device's camera. Device's camera is driving my crazy. I am using below code to allow user to capture images. Sometimes camera shows preview and sometimes doesn't. Instead of preview is just shows complete darkness on screen. If I switch from rear to front camera is starts working fine. I have even trying deleting all background apps from device and clearing as much memory as I could; still no luck and I am stuck. :(
- (IBAction)addNewImage:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
// Take picture from camera
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
// set no to take as much pictures as user want.
imagePicker.showsCameraControls = YES;
// Show user the camera
[self presentModalViewController:imagePicker
animated:YES];
}
else
{
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:imagePicker
animated:YES];
}
}
I have a customer who had this issue. They must have selected to not allow access to the camera. We had to change the camera privacy setting for the app in Settings. When we switched that back on, no more black camera screen.
I was facing the same issue in iOS7 for around a month, After a long long head breaking code review of the entire app, i was able to identify the problem.
I was enumerating an
IBOutletCollection(UILabel) NSArray *staticLabelsCollection;
array Concurrently updating the labels texts, which got executed simultaneously on multiple threads.
[self.labelsArr enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UILabel * label = (UILabel*)obj;
label.text=[NSString stringWithFormat:#"%d",idx+2];
}];
This created the problem of updating the UIKit elements on other than main thread.
I was able to catch the this issue by enabling the environment variable CA_DEBUG_TRANSACTIONS=1 in Xcode which generated warnings in device console
Nov 20 18:40:26 iPad2 CameraTest[1757] <Warning>: CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
0 QuartzCore 0x32a553b3 <redacted> + 266
1 QuartzCore 0x32a55269 <redacted> + 224
2 QuartzCore 0x32a56871 <redacted> + 24
3 QuartzCore 0x32a56eed <redacted> + 40
4 QuartzCore 0x32a619ed <redacted> + 412
5 QuartzCore 0x32a6184b <redacted> + 46
6 QuartzCore 0x32a61819 <redacted> + 44
7 UIKit 0x32ddfe53 <redacted> + 86
8 CameraTest 0x000923b5 __35-[ViewController blockEnumeration:]_block_invoke + 184
9 CoreFoundation 0x305aa821 <redacted> + 92
10 libdispatch.dylib 0x3b3308eb <redacted> + 134
11 libdispatch.dylib 0x3b32fd71 <redacted> + 220
12 libdispatch.dylib 0x3b32ff59 <redacted> + 56
13 libsystem_pthread.dylib 0x3b46adbf _pthread_wqthread + 298
14 libsystem_pthread.dylib 0x3b46ac84 start_wqthread + 8
Fixing these 'uncommited CATransactions' by forcing them to run on the main thread fixed the black camera issues.
I was able to fix it by removing Option: NSEnumerationConcurrent from enumeration.
The sample app which could constantly reproduce the problem can be downloaded here
Hope the sample app could give some insight and the work around for the issue.
I had faced this issue in my app. Though I never found out the what the issue was, I rewrote my code to define a property of UIIMagePickerController type and initialize it once in the getter. Used this property to initialize the camera view :
getter:
-(UIImagePickerController *) imagePicker{
if(!_imagePicker){
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else{
_imagePicker.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;
}
}
return _imagePicker;
}
- (IBAction)addNewImage:(id)sender{
if (self.imagePicker)
{
[self presentViewController:self.imagePicker animated:YES completion:^{}];
}
}
For some reason this got rid of the issue with preview sometimes showing a black screen
In ios7, you should set mainWindow.rootViewController = a class has kind is UIViewController. It's work for me.
If rootViewController is other, ex: UITabbarController, UINavigationController..., the black screen of camera will appear.

Custom UIView causes a EXC_BAD_ACCESS code = 1 in layoutSubviews

I have created a custom UIView which is instantiated 3 times from UIViewController. From the viewDidLoad method of that UIViewController:
self.remainingDays = [[RemainingTileView alloc] initWithFrame:CGRectMake(20, 49, 80, 75)];
self.remainingHours = [[RemainingTileView alloc] initWithFrame:CGRectMake(120, 49, 80, 75)];
self.remainingMinutes = [[RemainingTileView alloc] initWithFrame:CGRectMake(220, 49, 80, 75)];
[self.view addSubview:self.remainingDays];
[self.view addSubview:self.remainingHours];
[self.view addSubview:self.remainingMinutes];
In the RemainingTileView class, I have this layoutSubviews method:
- (void)layoutSubviews {
[super layoutSubviews];
if (self.number) // This is an NSNumber property
self.numberLabel = [self labelForNumber:[self.number intValue]];
else
self.numberLabel = [self labelForNumber:0];
if (self.unit) // This is an NSString property
self.unitLabel = [self labelForUnit:self.unit];
else
self.unitLabel = [self labelForUnit:#""];
[self configView];
}
When creating the view, it crashes on the line if (self.number) with the stack frame:
* thread #1: tid = 0x2403, 0x39f6c526 libobjc.A.dylib`objc_retain + 6, stop reason = EXC_BAD_ACCESS (code=1, address=0x10000010)
frame #0: 0x39f6c526 libobjc.A.dylib`objc_retain + 6
frame #1: 0x000dc742 myProject`-[RemainingTileView layoutSubviews](self=0x1e892b80, _cmd=0x344cde51) + 106 at RemainingTileView.m:63
frame #2: 0x3405d802 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 258
frame #3: 0x33e07d8a QuartzCore`-[CALayer layoutSublayers] + 214
frame #4: 0x33e07928 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 460
frame #5: 0x33e0885c QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
frame #6: 0x33e08242 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 238
frame #7: 0x33e08050 QuartzCore`CA::Transaction::commit() + 316
frame #8: 0x33e07eb0 QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 60
frame #9: 0x322276cc CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 20
frame #10: 0x322259c0 CoreFoundation`__CFRunLoopDoObservers + 276
frame #11: 0x32225d16 CoreFoundation`__CFRunLoopRun + 742
frame #12: 0x32198ebc CoreFoundation`CFRunLoopRunSpecific + 356
frame #13: 0x32198d48 CoreFoundation`CFRunLoopRunInMode + 104
frame #14: 0x35d6f2ea GraphicsServices`GSEventRunModal + 74
frame #15: 0x340ae300 UIKit`UIApplicationMain + 1120
frame #16: 0x000d3448 Project Countdown`main(argc=1, argv=0x2fd2ecf8) + 116 at main.m:17
self.number is an instance of NSNumber.
The UI is being modified from the main thread. I have looked for existings solutions here on stackoverflow but nothing worked.
What am I missing? What should I look for?
Looks like your properties have incorrect declarations. Probably assign or weak instead of retain, copy, or strong.
It looks like the property is returning some invalid object and ARC is attempting to retain it, which then fails. It looks like you might be better off moving your check for nil values into a custom property accessor, something along the lines of:
- (NSNumber *)number {
if (_number == nil) {
_number = [NSNumber numberWithInt:0];
}
return _number;
}
Then you can simply set the numberLabel value to number without having to check here. You can do something similar for unit as well.

How to prevent crash on Cancel of MFMailComposeViewController?

Somewhere:
if([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *email_vc = [[MFMailComposeViewController alloc] init];
email_vc.mailComposeDelegate = self;
[email_vc setSubject:subject];
[email_vc setMessageBody:message isHTML:FALSE];
[email_vc setToRecipients:recipients];
[self presentModalViewController:email_vc animated:FALSE];
[[UIApplication sharedApplication] setStatusBarHidden:TRUE];
[email_vc release];
}
else
...
Somewhere else:
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"Saved");
break;
case MFMailComposeResultSent:
NSLog(#"Sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Compose result failed");
break;
default:
NSLog(#"Default: Cancelled");
break;
}
// This ugly thing is required because dismissModalViewControllerAnimated causes a crash
// if called right away when "Cancel" is touched.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_current_queue(), ^
{
[self dismissModalViewControllerAnimated:FALSE];
});
}
That ugly "dispatch_after" block is the only way I can get this to work without a crash.
The context is that touching anything other than "Send" on the email compose view controller will cause a crash. Is there a way to deal with this without having to resort to this ugly band-aid? My theory on the band-aid is that an intermediate view is being presented when you touch "Cancel" to confirm that the user really wants to cancel. I am wondering if [self dismissModalViewControllerAnimated:FALSE]; is trying to dismiss a view out of sequence or something to that effect. By inserting a small delay I am theorizing that the mail compose view has time to cleanup before it is asked to go away.
I've seen a delay used in another question. The author did not go into any details though:
Crash On MFMailComposeViewController For iPad
EDIT 1: Adding crash log
Incident Identifier: ****************
CrashReporter Key: *****************
Hardware Model: iPhone4,1
Process: ************* [9038]
Path: /var/mobile/Applications/*********************
Identifier: ***********************
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2012-07-20 11:25:53.704 -0700
OS Version: iPhone OS 5.0.1 (9A405)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xa003853a
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x316b9fbc 0x316b6000 + 16316
1 UIKit 0x350caa9e 0x34f8e000 + 1297054
2 UIKit 0x34fa6814 0x34f8e000 + 100372
3 UIKit 0x34fabfb2 0x34f8e000 + 122802
4 QuartzCore 0x33354ba0 0x33329000 + 179104
5 libdispatch.dylib 0x37896f74 0x37894000 + 12148
6 CoreFoundation 0x37bac2d6 0x37b20000 + 574166
7 CoreFoundation 0x37b2f4d6 0x37b20000 + 62678
8 CoreFoundation 0x37b2f39e 0x37b20000 + 62366
9 GraphicsServices 0x376adfc6 0x376aa000 + 16326
10 UIKit 0x34fbf73c 0x34f8e000 + 202556
11 ***************** 0x00002346 main (main.m:14)
12 ***************** 0x00002304 start + 32
EDIT 2: After much head scratching it appears that this is a genuine Apple bug.
I downloaded and ran the MailComposer sample project:
http://developer.apple.com/library/ios/#samplecode/MailComposer/Introduction/Intro.html
It works fine.
Then I edited the code to remove the animation while presenting and dismissing the mail composition controller.
[self presentModalViewController:picker animated:FALSE];
and
[self dismissModalViewControllerAnimated:FALSE];
Sure-enough, it crashed when "Cancel" was used to dismiss the email composition UI.
Running zombie brought this out:
-[MFMailComposeController actionSheet:didDismissWithButtonIndex:]: message sent to deallocated instance 0x7479ef0
I guess the action sheet gets the dismiss message instead of the mail compose view controller.
If someone could confirm behavior I'll report the bug.
EDIT 3: Bug reported.
The answer I accepted has a good explanation of the potential mechanism that is causing this issue. Also, during the back and forth in the answer comments two additional work-arounds were identified. All band-aids but now there are a few choices.
I haven't checked yet, but I suspect that ShareKit is subject to this bug as well (if the presentation of the mail compose view controller is not animated).
I guess the action sheet gets the dismiss message instead of the mail compose view controller.
Not quite.
The sequence of events probably happens like this:
Action sheet calls -actionSheet:clickedButtonAtIndex: on its delegate (the MFMCVC).
MFMailComposeViewController calls -mailComposeController:didFinishWithResult:error: on its delegate (your VC)
Your VC calls [self dismissModalViewControllerAnimated:NO]
This causes the MFMCVC to be released. Since the dismiss isn't animated, there is no longer anything referring to the MFMCVC. It gets dealloced!
Action sheet calls -actionSheet:didDismissWithButtonIndex: on its delegate
But its delegate has been dealloced!
So it crashes!
The fix would be for Apple to do actionSheet.delegate = nil in -dealloc.
A potential workaround
[[self.modalViewController retain] autorelease]
[self dismissModalViewControllerAnimated:NO]
This is a bit trickier to do if you are using ARC.
this works for me:
- (void) mailComposeController: (MFMailComposeViewController *) controller
didFinishWithResult: (MFMailComposeResult) result
error: (NSError *) error {
if(result == MFMailComposeResultSent){
[self dismissViewControllerAnimated:YES completion:NULL];
} else if (result == MFMailComposeResultCancelled) {
[self dismissViewControllerAnimated:YES completion:NULL];
}
}

MGTwitterEngine and its Supported Arrays

This is my first time posting. I have been afraid to post anything since I am a noob with C++ but I do have to say I seem to be catching on fairly quick since I am an experienced html, css, javascript developer.
Ok so I am working on this project that implements twitter and Matts TwitterEngine and things are starting to come together. I have a tableview collecting the timeline of the user who signs in. You can make tweets and see the timeline but I am running into a few problems while trying to incorporate the "#"user" attribute.
I have come to conclusion that it is because it is a NSDictionary with several arrays within in it itself. For example #user consist of User, scree_name, ect so here is some code to maybe see if anybody can help me sort this out a little.
In the .h file of a NSObject I will call out a
-(NSString*)author;
In the .m file
#implementation Tweet
-(id)initWithTweetDictionary:(NSDictionary*)_contents {
if(self == [super init]) {
contents = _contents;
[contents retain];
}
return self;
}
-(NSString*)author {
return [[contents objectForKey:#"user"] objectForKey:#"screen_name"];
}
Now this is where I call it to a View and believe I have issues becuase I am still learning Arrays and Mutable Arrays and not sure what to call.
In my TwitterViewController.h
I first obviously import SA_OAuth engine and controller which work fine then I use two MutableArrays like below
MGTwitterEngine *_twitter;
SA_OAuthTwitterEngine *_engine;
NSMutableArray *tweets;
NSMutableArray *authors;
in the twitterview.m I import the first .h and then call out
//Connect to twitter API
- (void)viewDidAppear:(BOOL)animated {
if(_engine) return;
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey = #"key here =P";
_engine.consumerSecret = #"secret here =P";
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];
if (controller)
[self presentModalViewController: controller animated: YES];
else {
tweets = [[NSMutableArray alloc] init];
authors = [[NSMutableArray alloc] init];
Then I returns the count of that MutableArray and try to display it next to the tweets so it shows the persons screen_name of the actual tweet on the timeline
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
//add subtitle
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
[cell.textLabel setNumberOfLines:7];
[cell.textLabel setText:[(Tweet*)[tweets objectAtIndex:indexPath.row] tweet]];
//-------THIS IS WHERE I KEEP GETTING A SIGBRT DURING LOAD "dump saying return count 0-----------[cell.textLabel setText:[(Tweet*)[authors objectAtIndex:indexPath.row] author]];------
//[cell.detailTextLabel setText:[(Tweet*)[retweetCount objectAtIndex:indexPath.row] reTweetCount]];
#pragma mark SA_OAuthTwitterController Delegate
- (void) OAuthTwitterController: (SA_OAuthTwitterController *) controller authenticatedWithUsername: (NSString *) username {
NSLog(#"Authenticated with user %#", username);
tweets = [[NSMutableArray alloc] init];
authors =[[NSMutableArray alloc] init];
[self updateStream:nil];
}
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier {
tweets = [[NSMutableArray alloc] init];
for(NSDictionary *d in statuses) {
NSLog(#"See dictionary: %#", d);
Tweet *tweet = [[Tweet alloc] initWithTweetDictionary:d];
[tweets addObject:tweet];
[retweetCount addObject:tweet];
[tweet release];
}
[self.tableView reloadData];
}
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier {
authors = [[NSMutableArray alloc] init];
for (NSDictionary *d in userInfo) {
NSLog(#"See dictionary: %#", d);
Tweet *tweet = [[Tweet alloc] initWithTweetDictionary:d];
[authors addObject:tweet];
[tweet release];
}
[self.tableView reloadData];
}
So like I said the "tweets" are working and I can add in other objects by addObject method such as retweet count but I can not for the life of me figure out why I cant get the User screen name to display in the cell!!!
I also eventually want to Async with the avatars and add a RT button so if anyone has any suggestions on an EASY way to implement those that would be great too!
I appreciate any help I can get !!! Thanks hope to hear from some one soon to help enlighten me about NSDictionary, NSArrays and MutableArrays cause I believe thats were the problem lays. Or maybe I am just not populating the table correctly whatever it is man I am stumpped and could use some help!
Thanks sincerely
Anthony
DUMP:
2011-05-29 03:27:21.477 ThemeCatcher[10409:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
*** Call stack at first throw:
(
0 CoreFoundation 0x01524be9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x016795c2 objc_exception_throw + 47
2 CoreFoundation 0x0151a6e5 -[__NSArrayM objectAtIndex:] + 261
3 ThemeCatcher 0x00024498 -[TwitterVeiwController tableView:cellForRowAtIndexPath:] + 600
4 UIKit 0x008037fa -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 634
5 UIKit 0x007f977f -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
6 UIKit 0x0080e450 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
7 UIKit 0x00806538 -[UITableView layoutSubviews] + 242
8 QuartzCore 0x004a8451 -[CALayer layoutSublayers] + 181
9 QuartzCore 0x004a817c CALayerLayoutIfNeeded + 220
10 QuartzCore 0x004a137c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
11 QuartzCore 0x004a10d0 _ZN2CA11Transaction6commitEv + 292
12 QuartzCore 0x004d17d5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
13 CoreFoundation 0x01505fbb __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
14 CoreFoundation 0x0149b0e7 __CFRunLoopDoObservers + 295
15 CoreFoundation 0x01463bd7 __CFRunLoopRun + 1575
16 CoreFoundation 0x01463240 CFRunLoopRunSpecific + 208
17 CoreFoundation 0x01463161 CFRunLoopRunInMode + 97
18 GraphicsServices 0x01f42268 GSEventRunModal + 217
19 GraphicsServices 0x01f4232d GSEventRun + 115
20 UIKit 0x0079e42e UIApplicationMain + 1160
21 ThemeCatcher 0x00002c29 main + 121
22 ThemeCatcher 0x00002ba5 start + 53
23 ??? 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Current language: auto; currently objective-c
(gdb)
UPDATED!!!!!! Want to post my solution incase others read this. I hate browsing post and users find their awnser but do not share their solution to help others in the future. So I wont be that guy and tell you all how I got this to work!
Solution:
First Correctly call out your Arrays like Danny talks about below do NOT follow the method I was it can cause issue for yourself later down the road. " I still used MutableArray on both call but will attempt to change in the near future.
Now make sure all Arrays are formatted properly and "connect your dots" =P
But here is the Kicker! Below is a part of MGTwitterEngine that explains my issue. At first I was calling a integer of "1" which the engine thought I was trying to get one "screen_name" for a whole array of users so obviously it would though a SIGABRT and say WTH are you trying to do here! =P
Just want to clarify what I said earlier about Integers and defining the user. In
MGTwitterRequestTypes.h towards the bottom theres this line of code:typedef enum _
MGTwitterResponseType {
MGTwitterStatuses = 0, // one or more statuses
MGTwitterStatus = 1, // exactly one status
MGTwitterUsers = 2, // one or more user's information
MGTwitterUser = 3, // info for exactly one user
MGTwitterDirectMessages = 4, // one or more direct messages
MGTwitterDirectMessage = 5, // exactly one direct message
MGTwitterGeneric = 6, // a generic response not requiring parsing
MGTwitterMiscellaneous = 8, // a miscellaneous response of key-value pairs
MGTwitterImage = 7, // an image
#if YAJL_AVAILABLE
MGTwitterSearchResults = 9, // search results
#endif
} MGTwitterResponseType;
// This key is added to each tweet or direct message returned,
// with an NSNumber value containing an MGTwitterRequestType.
// This is designed to help client applications aggregate updates.
define TWITTER_SOURCE_REQUEST_TYPE #"source_api_request_type"
I hope I i have help others to accomplish adding scree_name...and basically you can use this for any "text" information within there such as ReTweet Counts ect... ect...
Now I need to figure out how to load thier profile images in the tableview .... I have it loading the images with this line of code but it wont load in the table view for some odd reason. It even pushes the text over correctly like their is an image there but there is not one
Any Suggestions on this would be greatly appreciated!!!
NSString *imageurl = [avatarsURL objectAtIndex:0];
NSLog(#"http://api.twitter.com/1/users/profile_image/username.json");
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]];
UIImage *tableImage = [[UIImage alloc] initWithData:imageData];
[cell.imageView setImage:tableImage];
CGSize imageSize = CGSizeMake(45,40);
UIGraphicsBeginImageContext(imageSize);
CGRect imageRect = CGRectMake(0.2, 0.1, imageSize.width, imageSize.height);
[tableImage drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
....I get no errors at all just this in the dump " I have to remove the HyperLinks because spam issues and I am a new member....FYI"
2011-05-29 17:26:02.950 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.980 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.981 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.982 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.983 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.984 ThemeCatcher[2974:207]
http:api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.985 ThemeCatcher[2974:207]
http://api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:02.987 ThemeCatcher[2974:207]
http://api.twitter.com/1/users/profile_image/username.json
2011-05-29 17:26:06.550 ThemeCatcher[2974:207] Request Suceeded: BF0E18DB-A2CC-4823-AC02-
6E182127BBF7
I can leave 2 =P
Okay, there are a few problems (I'll save the memory-management related stuff for last):
General Problems
First of all, how does your implementation of numberOfSectionsInTableView: and tableView:numberOfRowsInSection: look like?
Next, every time your viewDidAppear: is called and you are already logged in you basically forget about all the old tweets: tweets = [[NSMutableArray alloc] init];
But what's even more problematic, is that you do so every time you receive data, as well:
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier {
tweets = [[NSMutableArray alloc] init]; // <= No!
...
}
And then there is this problem which I don't understand because I don't know the library: What's the difference between your authors and yout tweets? (Both are arrays of tweets — frankly, I don't see the point.)
If understood your crash correctly, it happens when you try to retrieve a tweet from the authors array and you assume that your authors array has at least the same number of objects in it, as the tweets array.
I don't know MGTwitterEngine well, but from what I infer from its documentation, userInfoReceived:forRequest: will only be called after you sent an explicit request for a users profile.
So it doesn't come as a surprise, that your assumption is apparently wrong.
Furthermore, you should be able to get all the info you need to display a tweet in the timeline from the tweet itself anyway (well except the actual image-data of the avatar, that is).
Memory Management
You are leaking every tweet you will ever receive:
Although you take care of correctly releasing every individual tweet after adding it to the tweets or authors array (good), you forget about those arrays whenever new data comes in. You probably shouldn't replace the entirety of said arrays in the first place and — instead — simply add the new stuff to them, but since you decided to go that route, make sure to release the old array before you assign the new one.
Personally, I'd suggest a different approach and create the tweets array only once in initWithStyle:, (and don't bother creating an authors array at all) only adding to and removing from it as needed — properly disposing of it in dealloc and calling removeAllObjects on it, when a user logs out (if you don't dispose of the view controller entirely, in this case).