1

我正在使用 5 个屏幕的 iPhone 应用程序。我想刷新 UITabBarController 中第 4 个屏幕中的值。我在 AppDelegate 中添加了@protocol,但它没有调用。这是我第一次使用@protocol,你能帮我解决这个问题吗?

AppDelegate.h

@protocol ReloadViewControllerDelegate <NSObject>

-(void) refreshViewController:(NSString *)result;

@end

id refreshViewControllerDelegate;

@property (nonatomic, retain) id refreshViewControllerDelegate;

我已经合成了。

AppDelegare.m中

@synthesize refreshViewControllerDelegate;

if ([refreshViewControllerDelegate conformsToProtocol:@protocol(ReloadViewControllerDelegate)]) 
{
   [refreshViewControllerDelegate performSelectorOnMainThread:@selector(refreshViewController:) withObject:@"YES" waitUntilDone:NO];                
}// Control not come inside of if Condition.... From here i want to update the fourthViewController..

但是control not go inside of the if condition。你能指导我哪里做错了吗?

在我的第四个 ViewController.h

#import "AppDelegate"

@interface fourthViewController : UIViewController <ReloadViewControllerDelegate>

在我的第四个 ViewController.m

-(void) refreshViewController:(NSString *)result
{
    NSLog(@"Result : %@", result);
}

谁能帮我做到这一点?提前致谢。

4

4 回答 4

0

您需要像这样声明您的委托:

@property (nonatomic, weak) IBOutlet id<ReloadViewControllerDelegate> delegate;

id 可以工作,但是通过使用 <>,您可以确保您分配的委托实际上正在实现协议,您可能仍然需要确保它响应选择器,但前提是某些方法被声明为

@optional

确保你合成它,最重要的是确保你设置它,它不是零。

于 2012-08-17T12:33:09.887 回答
0

您收到警告是因为您将委托键入为id. Anid是泛型类型,这意味着编译器不知道哪些方法或属性可能可用。为了消除您的警告,将您的委托声明为 NSObject:

@property (nonatomic, retain) NSObject <ReloadViewControllerDelegate> *refreshViewControllerDelegate;

通过声明为 NSObject,编译器现在知道 NSObject 拥有的所有方法,然后您可以调用:

-performSelectorOnMainThread:withObject:waitUntilDone:

在你的代表身上没有警告。祝你好运!

于 2012-08-17T13:06:35.943 回答
0

试试这个:

@protocol ReloadViewControllerDelegate <NSObject>

-(void) refreshViewController:(NSString *)result;

@end

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (weak) id <ReloadViewControllerDelegate>refreshViewControllerDelegate;
@end

在 AppDelegate.m

@implementation AppDelegate
@synthesize window, refreshViewControllerDelegate;

...

这里 Tab4ViewController 是类的名称。

    if ([Tab4ViewController conformsToProtocol:@protocol(ReloadViewControllerDelegate)]) 
    {
       [refreshViewControllerDelegate performSelectorOnMainThread:@selector(refreshViewController:) withObject:@"YES" waitUntilDone:NO];                
    }

...
@end


#import "AppDelegate.h"

@interface Tab4ViewController<ReloadViewControllerDelegate>
...
@end

@implementation Tab4ViewController

...
appDelegate.refreshViewControllerDelegate = self;
...

@end
于 2012-08-17T13:41:51.303 回答
-1

您正在调用此代码:

if ([refreshViewControllerDelegate conformsToProtocol:@protocol(ReloadViewControllerDelegate)]) 

但这refreshViewControllerDelegate是不是:

id refreshViewControllerDelegate;

conformsToProtocol检查对象是否声明它符合协议,而您的则不。如果要指定对协议的符合性,您需要:

id<ReloadViewControllerDelegate> refreshViewControllerDelegate;

编辑

好的,关于performSelectorOnMainThread问题...该方法在 NSThread 的类别中提供,并且未在 NSObject 协议中声明。所以,如果你想调用它,那么你需要将你的类型声明为 NSObject,它符合你的协议。

NSObject<ReloadViewControllerDelegate> refreshViewControllerDelegate;

编辑

好的,看起来这不是一个关于使用协议的简单问题,而是一个完整的教程。由于 SO 不是这样的地方,我将尝试给出一个简短的...

协议是一个接口声明。

@protocol ReloadChatViewControllerDelegate <NSObject>
- (void)refreshViewController:(NSString *)result;
@end

那就是说镇上有一个新协议,名称ReloadChatViewControllerDelegate和它也符合NSObject协议。任何采用新协议的类都必须提供refreshViewController. 您可以通过放入一个@optional部分来使协议方法成为可选方法。

@protocol ReloadChatViewControllerDelegate <NSObject>
- (void)refreshViewController:(NSString *)result;
@optional
- (void)optRefresh;
@end

现在,让我们将协议的采用留到以后。假设您正在编写通用代码,并且您只想知道给定的对象是否符合协议,如果符合,请在其上调用方法。就像是...

@interface Bar : NSObject
@property (nonatomic, weak) NSObject<ReloadChatViewControllerDelegate>  *refreshViewControllerDelegate;
- (void)blarg;
@end

现在,Bar 类提供了一个委托属性,以便它可以提供一些对象来帮助它完成一些工作。但是,该委托对象必须至少是NSObject, 并且符合ReloadChatViewControllerDelegate协议。

现在,ObjC(和 C)是相当宽松的,所以你可以强制一个对象是你想要的任何类型,但是你应该得到你得到的崩溃。现在,当blarg被调用时,会通知委托人做一些工作。

由于委托的属性类型已经表明它符合给定的协议,因此无需检查是否符合。我们可以调用委托方法。请注意,我们必须查看对象是否实现了任何可选的协议方法。

@implementation Bar
@synthesize refreshViewControllerDelegate = _refreshViewControllerDelegate;
- (void)blarg {
    // Do something, then invoke the delegate
    [self.refreshViewControllerDelegate
        performSelectorOnMainThread:@selector(refreshViewController:)
                         withObject:@"YES"
                      waitUntilDone:NO];
    if ([self.refreshViewControllerDelegate respondsToSelector:@selector(optRefresh)]) {
        [self.refreshViewControllerDelegate optRefresh];
    }
}
@end

但是,如果您想成为通用的,并接受任何对象作为委托(也许您想让委托符合某个给定的协议是可选的),那么您可以接受一个普通的id,然后检查它是否符合。在这种情况下,您可以将您的委托声明为一个 id(或其他类型)。

@property (nonatomic, weak) id refreshViewControllerDelegate;

现在,在您的代码中,您需要检查一致性。

- (void)blarg {
    // Do something, then invoke the delegate
    if ([self.refreshViewControllerDelegate
            conformsToProtocol:@protocol(ReloadChatViewControllerDelegate)]) {
        [self.refreshViewControllerDelegate
            performSelectorOnMainThread:@selector(refreshViewController:)
                             withObject:@"YES" waitUntilDone:NO];
        if ([self.refreshViewControllerDelegate
                respondsToSelector:@selector(optRefresh)]) {
            [self.refreshViewControllerDelegate optRefresh];
        }
    }
}

好的,现在您已经定义了一个协议,并且您有调用该协议上的方法的代码。两个警告。

首先,必须将委托设置为一个对象。 nil将响应false任何方法,因此它当然不会遵守,也不会在发送任何消息时做任何事情。

其次,您必须确保您的委托声明符合协议。仅仅实现这些方法是不符合的。如果一个类没有明确指定它符合协议,那么conformsToProtocol即使它实现了协议的方法,它也会返回 false。

所以,让我们指定一些符合协议的类作为我们的委托。

@interface Foo : NSObject<ReloadChatViewControllerDelegate>
- (void)refreshViewController:(NSString *)result;
@end
@implementation Foo
- (void)refreshViewController:(NSString *)result {
    NSLog(@"Look, ma, I'm refreshed with %@", result);
}
@end

它符合协议,提供强制方法的实现,省略可选方法。

现在,如果你运行这段代码,你应该会看到这段奇妙的代码。

Foo *foo = [[Foo alloc] init];
Bar *bar = [[Bar alloc] init];
bar.refreshViewControllerDelegate = foo;
[bar blarg];
于 2012-08-17T12:32:18.193 回答