自定义代理无法正常工作

时间:2011-08-26 13:05:36

标签: iphone objective-c delegates exc-bad-access retain

我已经开始与代理人合作,正如我提出的另一个问题所建议的那样。现在,我已经创建了一个名为ProfileViewController的UIViewController,我希望从Facebook加载新闻源。我还有NSObject的子类叫FBFeed。此子类加载Facebook News Feed并应将其传递回视图控制器。我对Facebook的所有请求都是通过一个名为FBRequestWrapper的单身人士发送的,在这种情况下,我会将结果传递给FBFeed

我在getFBRequestWithGraphPath:andDelegate:中调用FBRequestWrapper,它将调用Facebook iOS SDK中的方法,该方法将委托作为参数。如果我输入self(这将是FBRequestWrapper)它可以正常工作。如果我放入_delegate(这是FBFeed的一个实例),则应用程序会与EXC_BAD_ACCESS崩溃。

我有理论说它可能会崩溃。我读过那个

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

应该是

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

但是这样做时我收到以下错误:

  

针对unsafe_unretained属性'委托'的现有ivar'委托'   必须是__unsafe_unretained

另外,我不知道是否足以让应用程序崩溃。

这是我的代码。

ProfileViewController.h

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

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

- (void)loadFeed;

@end

ProfileViewController.m

@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

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

@protocol FBFeedDelegate;

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

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

- (void)loadNewsFeedWithDelegate:(id)_delegate;

@end


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

FBFeed.m

#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

#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

#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

3 个答案:

答案 0 :(得分:8)

我猜您正在使用ARC和仍在NDA下的新iOS5 SDK。而不是使用保留,使用关键字'strong'。使用strong将具有与使用retain相同的行为。像这样设置你的房产:

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

答案 1 :(得分:1)

我认为您有两种方式:

  1. 请勿使用ARC并保留代码

  2. 如果您想使用ARC,请注意不应保留代理。但是当使用ARC时,这样的ivar声明:

  3. id <FBFeedDelegate> delegate

    默认为

    id <FBFeedDelegate> __strong delegate
    

    所以当你声明这样的属性时:

    @property (readwrite, unsafe_unretained) id <FBFeedDelegate> delegate
    

    伊娃应该是这样的:

    id <FBFeedDelegate> __unsafe_unretained delegate
    

答案 2 :(得分:0)

我遇到了同样的问题但是我能够在XCode 4.3.2上的iOS 5.1下正常运行

在.h文件中使用此代码

@protocol AnimationManagerCountdownTimerDelegate <NSObject>
@required
    -(void)countdownCompleted;

@end


@interface AnimationManager : NSObject{
....
}

@property (nonatomic, strong) id <AnimationManagerCountdownTimerDelegate> countdownTimerDelegate;

@end

然后在.m文件中你只需合成:

@synthesize countdownTimerDelegate;