自定义委托不工作
正如我提出的另一个问题中所建议的,我已经开始更多地与代表合作。现在,我创建了一个名为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我猜您正在使用 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;
我认为您有两种方法:
不要使用 ARC 并保持代码原样
如果您想使用 ARC,请注意,通常不应保留代表。但是当使用 ARC 时,ivar 声明如下:
id; delegate
默认为
因此,当您声明如下属性时:
ivar 应该如下所示:
I think there are two ways for you:
Don't use ARC and leave your code as it was
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
So when you declare a property like this:
The ivar should look like this:
我遇到了同样的问题,但后来我能够使其在 XCode 4.3.2 上的 iOS 5.1 下正常工作
在您的 .h 文件中使用此代码
然后在 .m 文件中您只需合成:
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
Then in the .m file you simply synthesize: