Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

SimonBS

macrumors regular
Original poster
Dec 30, 2009
202
0
Hello,

For the first time I am trying to create my own delegate.
Now, I have made a UIViewController called ProfileViewController in which I would like to load the News Feed from Facebook. I also have a subclass of NSObject called FBFeed. This subclass loads the Facebook News Feed and should pass it back to the view controller. All my requests to Facebook are sent through a singleton named FBRequestWrapper which (in this case) should pass the result to FBFeed.

I call getFBRequestWithGraphPath:andDelegate: in FBRequestWrapper which will call a method in the Facebook iOS SDK which takes a delegate as a parameter. If I put in self (which will be the FBRequestWrapper) it works just fine. If I put in _delegate (which is an instance of FBFeed) the application crashes with "EXC_BAD_ACCESS".

Does anyone have an idea what I might be doing wrong?

Here is my code.

ProfileViewController.h

Code:
#import <UIKit/UIKit.h>
#import "FeedTableView.h"
#import "FBFeed.h"

@interface ProfileViewController : UIViewController <FBFeedDelegate>
{
    FeedTableView *tableView;
}

- (void)loadFeed;

@end

ProfileViewController.m

Code:
@implementation ProfileViewController

- (void)loadFeed
{
    FBFeed *feed = [[FBFeed alloc] init];
    [feed loadNewsFeedWithDelegate:self];
}

#pragma mark -
#pragma FBFeedDelegate

- (void)finishedLoadingFeed:(FBFeed *)_feed
{
    NSLog(@"ProfileViewController: FBFeed Finished.");
}

- (void)failedToLoadFeed:(FBFeed *)_feed
{
    NSLog(@"ProfileViewController: FBFeed Failed.");
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Load feed
    [self loadFeed];
}

@end

FBFeed.h

Code:
#import <Foundation/Foundation.h>
#import "FBRequestWrapper.h"

@protocol FBFeedDelegate;

@interface FBFeed : NSObject <FBRequestDelegate>
{
    id <FBFeedDelegate> delegate;
}

@property (nonatomic, assign) id <FBFeedDelegate> delegate;

- (void)loadNewsFeedWithDelegate:(id)_delegate;

@end


@protocol FBFeedDelegate <NSObject>
@required
- (void)finishedLoadingFeed:(FBFeed *)_feed;
- (void)failedToLoadFeed:(FBFeed *)_feed;
@end

FBFeed.m

Code:
#import "FBFeed.h"

@implementation FBFeed

@synthesize delegate;

- (void)loadNewsFeedWithDelegate:(id)_delegate
{
    self.delegate = _delegate;

    [[FBRequestWrapper defaultManager] getFBRequestWithGraphPath:@"me" andDelegate:self];
}

#pragma mark -
#pragma mark FBRequest Delegate

- (void)request:(FBRequest *)request didLoad:(id)result
{
    NSLog(@"FBFeed: FBRequest Did Load.");
    NSLog(@"%@", result);
}

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"FBFeed: FBRequest Failed.");
    NSLog(@"%@", error);
}

@end

FBRequestWrapper.h

Code:
#import <Foundation/Foundation.h>
#import "FBConnect.h"

@interface FBRequestWrapper : NSObject <FBRequestDelegate, FBSessionDelegate>
{
    Facebook *facebook;
    BOOL isLoggedIn;
}

@property (nonatomic, assign) BOOL isLoggedIn;

+ (id)defaultManager;
- (void)setIsLoggedIn:(BOOL)_loggedIn;
- (void)FBSessionBegin:(id<FBSessionDelegate>)_delegate;
- (void)FBLogout;
- (void)getFBRequestWithGraphPath:(NSString *)_path andDelegate:(id)_delegate;
- (void)getFBRequestWithMethodName:(NSString *)_methodName andParams:(NSMutableDictionary *)_params andDelegate:(id)_delegate;

@end

FBRequestWrapper.m

Code:
#import "FBRequestWrapper.h"

static FBRequestWrapper *defaultWrapper = nil;

@implementation FBRequestWrapper
@synthesize isLoggedIn;

+ (id)defaultManager
{
    if(!defaultWrapper)
    {
        defaultWrapper = [[FBRequestWrapper alloc] init];
    }

    return defaultWrapper;
}

- (void)getFBRequestWithGraphPath:(NSString *)_path andDelegate:(id)_delegate
{
    if (_path != nil)
    {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

        if (_delegate == nil)
        {
            _delegate = self;
        }

        [facebook requestWithGraphPath:_path andDelegate:_delegate];
    }
}

#pragma mark -
#pragma mark FBRequestDelegate

- (void)request:(FBRequest *)request didLoad:(id)result
{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"%@", result);
}

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error
{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"FBRequest Failed: %@", error);
}

@end
 
What version of iOS are you working with?

Where are you releasing FBFeed?
 
Post the stack backtrace; it will help us help you.

This is what you mean, right? :)

Code:
#0  0x0195009f in objc_msgSend ()
#1  0x022ba424 in _XMLPlistAppendDataUsingBase64.__CFPLDataEncodeTable ()
#2  0x01496ac0 in ___NSURLConnectionDidReceiveResponse_block_invoke_0 ()
#3  0x01494df4 in __65-[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]_block_invoke_0 ()
#4  0x01495e17 in -[NSURLConnectionInternalConnection invokeForDelegate:] ()
#5  0x01494daf in -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] ()
#6  0x01494f35 in -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] ()
#7  0x013d95bb in _NSURLConnectionDidReceiveResponse ()
#8  0x02ac7a13 in URLConnectionClient::_clientSendDidReceiveResponse ()
#9  0x02b92ce0 in URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload ()
#10 0x02b92e31 in URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload ()
#11 0x02abf2b8 in URLConnectionClient::processEvents ()
#12 0x02b926e7 in non-virtual thunk to URLConnectionInstanceData::multiplexerClientPerform() ()
#13 0x02abf157 in MultiplexerSource::perform ()
#14 0x022339af in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#15 0x02196bf3 in __CFRunLoopDoSources0 ()
#16 0x021964d4 in __CFRunLoopRun ()
#17 0x02195e34 in CFRunLoopRunSpecific ()
#18 0x02195d4b in CFRunLoopRunInMode ()
#19 0x01cf59dd in GSEventRunModal ()
#20 0x01cf5aa2 in GSEventRun ()
#21 0x00aa9a1b in UIApplicationMain ()
#22 0x000029b8 in main (argc=1, argv=0xbffff5d4) at /Users/simonstoevring/Dropbox/Xcode/FaceApp/FaceApp/FaceApp/main.m:16

What version of iOS are you working with?

Where are you releasing FBFeed?

I am running iOS 5 beta 6 and Xcode 4.2 beta 6. FBFeed is not directly released as I am using ARC.
 
Last edited:
I don't grok ARC, but I'd be worried that the object assigned to the local variable feed in ProfileViewController's -loadFeed is being sent release prematurely.

Damn, my original post, was correct. I'm not typing it out again. In short, try holding a strong reference to the FBFeed object somewhere.
 
Last edited:
I don't grok ARC, but I'd be worried that the object assigned to the local variable feed in ProfileViewController's -loadFeed is being sent release prematurely.

Damn, my original post, was correct. I'm not typing it out again. In short, try holding a strong reference to the FBFeed object somewhere.

Actually, I have your original post here. I'll post it beneath my answer. It was a really good answer. It works now! I appreciate your help very much. Also a big thanks to the others in the thread who helped me out.

So it seems that with ARC the instance of FBFeed was released and when it wanted to respond to the delegate, FBFeed must have been nil. Correct me if I'm wrong :)

The original post from jiminaus:
jiminaus said:
I don't grok ARC, but I'd be worried that the object assigned to the local variable feed in ProfileViewController's -loadFeed is being sent release prematurely. Try creating a strong property in ProfileViewController and assign the FBFeed object created in loadFeed to that property. Then assign nil to the property in -finishedLoadingFeed: and -failedToLoadFeed:. This way it will surely not be prematurely released.

This is the code I ended up with to get it working:

ProfileViewController.h

Code:
#import <UIKit/UIKit.h>
#import "FeedTableView.h"
#import "FBFeed.h"

@interface ProfileViewController : UIViewController <FBFeedDelegate>
{
    FeedTableView *tableView;
    
    FBFeed *feed;
}

@property (nonatomic, strong) FBFeed *feed;

- (void)loadFeed;

@end

ProfileViewController.m

Code:
#import "ProfileViewController.h"

@implementation ProfileViewController

@synthesize feed;

- (void)loadFeed
{
    feed = [[FBFeed alloc] init];
    [feed loadNewsFeedWithDelegate:self];
}

#pragma mark -
#pragma FBFeedDelegate

- (void)finishedLoadingFeed:(FBFeed *)_feed
{
    NSLog(@"ProfileViewController: FBFeed Finished.");
    
    NSLog(@"%@", _feed);
    
    feed = nil;
    _feed = nil;
}

- (void)failedToLoadFeed:(FBFeed *)_feed
{
    NSLog(@"ProfileViewController: FBFeed Failed.");
    
    feed = nil;
    _feed = nil;
}

@end
 
Damn, my original post, was correct. I'm not typing it out again. In short, try holding a strong reference to the FBFeed object somewhere.

Exactly where I was going.


Code:
 feed = [[FBFeed alloc] init];

Are you sure you want to skip your accessor here?

Code:
self.feed = [[FBFeed alloc] init];

Arc will take care of the extra retain.
 
Exactly where I was going.


Code:
 feed = [[FBFeed alloc] init];

Are you sure you want to skip your accessor here?

Code:
self.feed = [[FBFeed alloc] init];

Arc will take care of the extra retain.

Ups, no. That was a mistake. I must admit that I am not yet keen on Objective-C but wouldn't you always have the accessors? Atleast if you are not 100% sure what you are doing.
 
Ups, no. That was a mistake. I must admit that I am not yet keen on Objective-C but wouldn't you always have the accessors? Atleast if you are not 100% sure what you are doing.

Yes, especially if your not sure.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.