Custom delegate not working

Discussion in 'iOS Programming' started by SimonBS, Aug 26, 2011.

  1. SimonBS macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #1
    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
     
  2. RonC macrumors regular

    Joined:
    Oct 18, 2007
    Location:
    Chicago-area
    #2
    Post the stack backtrace; it will help us help you.
     
  3. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #3
    What version of iOS are you working with?

    Where are you releasing FBFeed?
     
  4. SimonBS, Aug 27, 2011
    Last edited: Aug 27, 2011

    SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #4
    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
    I am running iOS 5 beta 6 and Xcode 4.2 beta 6. FBFeed is not directly released as I am using ARC.
     
  5. jiminaus, Aug 27, 2011
    Last edited: Aug 27, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #5
    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.
     
  6. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #6
    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:
    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
     
  7. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #7
    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.
     
  8. SimonBS thread starter macrumors regular

    SimonBS

    Joined:
    Dec 30, 2009
    #8
    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.
     
  9. Sykte macrumors regular

    Joined:
    Aug 26, 2010
    #9
    Yes, especially if your not sure.
     

Share This Page