自定义委托不工作

发布于 2024-12-01 17:05:57 字数 4762 浏览 0 评论 0原文

正如我提出的另一个问题中所建议的,我已经开始更多地与代表合作。现在,我创建了一个名为 ProfileViewController 的 UIViewController,我想在其中加载来自 Facebook 的新闻源。我还有一个名为 FBFeed 的 NSObject 子类。该子类加载 Facebook News Feed 并将其传递回视图控制器。我对 Facebook 的所有请求都是通过名为 FBRequestWrapper 的单例发送的,该单例(在本例中)应将结果传递给 FBFeed

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

我有一个理论为什么它可能会崩溃。我读过

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

应该是

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

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

unsafe_unretained 属性“delegate”的现有 ivar“delegate” 必须是 __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

I have started working more with delegate as suggested in another question I made. Now, I have made a UIViewController called ProfileViewController in which I would like to load the News Feed from Facebook. I also have 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.

I have a theory why it might crash. I have read that

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

should be

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

But when doing so I get the following error:

Existing ivar 'delegate' for unsafe_unretained property 'delegate'
must be __unsafe_unretained

Also, I don't know if that enough to make the application crash.

Here is my code.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

℉絮湮 2024-12-08 17:05:57

我猜您正在使用 ARC 和新的 iOS5 SDK,该 SDK 仍处于 NDA 状态。不要使用保留,而是使用关键字“strong”。使用strong 将具有与使用retain 相同的行为。像这样设置您的属性:

@property(非原子,强)id;委托;

I guess you are using ARC and the new iOS5 SDK which is still under NDA. Instead of using retain, use the Keyword 'strong'. Using strong will have the same behaviour intended as using retain. Set up your property like this:

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

游魂 2024-12-08 17:05:57

我认为您有两种方法:

  1. 不要使用 ARC 并保持代码原样

  2. 如果您想使用 ARC,请注意,通常不应保留代表。但是当使用 ARC 时,ivar 声明如下:

id; delegate

默认为

id <FBFeedDelegate> __strong delegate

因此,当您声明如下属性时:

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

ivar 应该如下所示:

id <FBFeedDelegate> __unsafe_unretained delegate

I think there are two ways for you:

  1. Don't use ARC and leave your code as it was

  2. If you want to use ARC, be aware that delegates normally shouldn't be retained. But when using ARC, an ivar declaration like this:

id <FBFeedDelegate> delegate

defaults to

id <FBFeedDelegate> __strong delegate

So when you declare a property like this:

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

The ivar should look like this:

id <FBFeedDelegate> __unsafe_unretained delegate
故人爱我别走 2024-12-08 17:05:57

我遇到了同样的问题,但后来我能够使其在 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;

I had the same problem but then I was able to make it work correctly under iOS 5.1 on XCode 4.3.2

Use this code in your .h file

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

@end


@interface AnimationManager : NSObject{
....
}

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

@end

Then in the .m file you simply synthesize:

@synthesize countdownTimerDelegate;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文