Пользовательский делегат не работает - PullRequest
0 голосов
/ 26 августа 2011

Я начал больше работать с делегатом, как было предложено в другом вопросе, который я задал.Теперь я создал UIViewController с именем ProfileViewController, в который я хотел бы загрузить новостную ленту из Facebook.У меня также есть подкласс NSObject с именем FBFeed.Этот подкласс загружает новостную ленту Facebook и должен передать ее обратно в контроллер представления.Все мои запросы в 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свойство 'делегат' должно быть __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 ]

8 голосов
/ 26 августа 2011

Полагаю, вы используете ARC и новый iOS5 SDK, который все еще находится под NDA.Вместо сохранения используйте ключевое слово «сильный».Использование strong будет иметь такое же поведение, как и использование retain.Настройте свою собственность следующим образом:

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

1 голос
/ 04 января 2012

Я думаю, что для вас есть два пути:

  1. Не используйте ARC и оставьте свой код таким, как он был

  2. Если выхотите использовать ARC, помните, что делегаты обычно не должны быть сохранены.Но при использовании ARC объявление ivar выглядит следующим образом:

id <FBFeedDelegate> delegate

по умолчанию

id <FBFeedDelegate> __strong delegate

Поэтому, когда вы объявляете свойство какэто:

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

Ивар должен выглядеть так:

id <FBFeedDelegate> __unsafe_unretained delegate
0 голосов
/ 13 мая 2012

У меня была такая же проблема, но потом я смог заставить ее корректно работать под iOS 5.1 на XCode 4.3.2

Используйте этот код в вашем .h файле

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

@end


@interface AnimationManager : NSObject{
....
}

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

@end

Затем в файле .m вы просто синтезируете:

@synthesize countdownTimerDelegate;
...