如何正确实施授权?

发布于 2024-07-30 04:55:48 字数 755 浏览 6 评论 0原文

我正在尝试为一个类实现委托,当特殊情况发生时,该类应该调用它的委托(如果有)。

从维基百科我有这个代码示例:

 @implementation TCScrollView
 -(void)scrollToPoint:(NSPoint)to;
 {
   BOOL shouldScroll = YES;
   // If we have a delegate, and that delegate indeed does implement our delegate method,
   if(delegate && [delegate respondsToSelector:@selector(scrollView:shouldScrollToPoint:)])
     shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point.

   if(!shouldScroll) return;  // If not, ignore the scroll request.

   /// Scrolling code omitted.
 }
 @end

如果我自己尝试这个,我会收到一条警告,指出未找到我在委托上调用的方法。 当然不是,因为委托只是通过 id 引用的。 它可以是任何东西。 当然在运行时这会工作得很好,因为我检查它是否响应选择器。 但我不希望 Xcode 中出现警告。 有更好的模式吗?

I'm trying to implement delegation for a class which should call it's delegate (if any), when special things happen.

From Wikipedia I have this code example:

 @implementation TCScrollView
 -(void)scrollToPoint:(NSPoint)to;
 {
   BOOL shouldScroll = YES;
   // If we have a delegate, and that delegate indeed does implement our delegate method,
   if(delegate && [delegate respondsToSelector:@selector(scrollView:shouldScrollToPoint:)])
     shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point.

   if(!shouldScroll) return;  // If not, ignore the scroll request.

   /// Scrolling code omitted.
 }
 @end

If I try this on my own, I get a warning that the method I am calling on the delegate was not found. Of course it was not, because the delegate is just referenced by id. It could be anything. Sure at runtime that will work fine because I check if it responds to selector. But I don't want the warning in Xcode. Are there better patterns?

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

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

发布评论

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

评论(3

空名 2024-08-06 04:55:48

您可以让委托具有实现 SomeClassDelegate 协议的 id 类型。 为此,您可以在 SomeClass 的标头(在您的情况下为 TCScrollView)中执行如下操作:

@protocol TCScrollViewDelegate; // forward declaration of the protocol

@interface TCScrollView {
    // ...
    id <TCScrollViewDelegate> delegate;
}
@property (assign) id<TCScrollViewDelegate> delegate;
@end

@protocol TCScrollViewDelegate
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to;
@end

然后您可以从您的实现中调用委托上的方法:

@implementation TCScrollView

-(void)scrollToPoint:(NSPoint)to;
{
  BOOL shouldScroll = YES;
  shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point.
  if(!shouldScroll) return;  // If not, ignore the scroll request.
  /// Scrolling code omitted.
}
@end

You could let the delegate be of the id type that implements the SomeClassDelegate protocol. For this, you could in the header of your SomeClass (in your case TCScrollView), do something like this:

@protocol TCScrollViewDelegate; // forward declaration of the protocol

@interface TCScrollView {
    // ...
    id <TCScrollViewDelegate> delegate;
}
@property (assign) id<TCScrollViewDelegate> delegate;
@end

@protocol TCScrollViewDelegate
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to;
@end

Then you can from your implementation, just call the method on the delegate:

@implementation TCScrollView

-(void)scrollToPoint:(NSPoint)to;
{
  BOOL shouldScroll = YES;
  shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]; // ask it if it's okay to scroll to this point.
  if(!shouldScroll) return;  // If not, ignore the scroll request.
  /// Scrolling code omitted.
}
@end
给我一枪 2024-08-06 04:55:48

跟进 drvdijk 的回答中的示例代码,如果调用委托方法时 delegate 可能为 nil,则可能会出现问题。

发送到 nil 的消息的返回值为 nil (又名 0.0 又名 0 又名 NO< /code>),因此如果 delegatenil

[delegate scrollView:self shouldScrollToPoint:to]

将返回 NO,这可能不是您的情况所需的行为。 首先检查会更安全:

if (delegate != nil) {
    shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]
}

此外,如果您不想在将 NSObject 声明的消息发送到委托时看到编译器警告(例如 respondsToSelector:),请包含协议声明中的 NSObject 协议:

@protocol TScrollViewDelegate <NSObject>
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to;
@end

Following up on the sample code in drvdijk's answer, there could be a problem if there is any chance that delegate could be nil when you call the delegate method.

The return value of a message sent to nil is nil (aka 0.0 aka 0 aka NO), so if delegate is nil,

[delegate scrollView:self shouldScrollToPoint:to]

will return NO, which might not be the desired behavior in your case. It's safer to check first:

if (delegate != nil) {
    shouldScroll = [delegate scrollView:self shouldScrollToPoint:to]
}

Also, if you don't want to see a compiler warning when sending messages declared by NSObject to your delegate (such as respondsToSelector:), include the NSObject protocol in your protocol declaration:

@protocol TScrollViewDelegate <NSObject>
- (BOOL) scrollView:(TCScrollView *)tcScrollView shouldScrollToPoint:(CGPoint)to;
@end
堇色安年 2024-08-06 04:55:48

使用[NSObject PerformSelector:]

[delegate performSelector:@selector(scrollView:shouldScrollToPoint:) withObject:self withObject:to];

您将不再收到编译器警告。

或者创建一个协议并在头文件中声明 MyProtocol *delegate

Use [NSObject performSelector:]

[delegate performSelector:@selector(scrollView:shouldScrollToPoint:) withObject:self withObject:to];

You won't get the compiler warnings anymore.

Alternatively create a prototcol and declare MyProtocol *delegate in header file.

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