2014-06-16 73 views
3

我向我的某個類添加了自定義協議,並且在prepareForSegue:方法嘗試設置委託時收到編譯器警告。我得到的警告是...獲取警告爲自定義協議設置代理

Sending 'MyCustomViewControllerClass *const __strong' to parameter of incompatible type 'id<NSFileManagerDelegate>' 

項目建立並運行,一切工作正常減去警告。如果我將<NSFileManagerDelegate>添加到我的自定義課程中,警告消失。我錯過了什麼或者這是Xcode(6測試版)中的錯誤?該代碼是建立一個協議/代表,但我會反正它張貼標準代碼...

SomeSecondClass.h

#import <UIKit/UIKit> 

@class SomeSecondCustomViewController; 

@protocol SomeSecondCustomViewControllerDelegate <NSObject> 
- (void)doThisForMe 
@end 

@interface SomeSecondCustomViewController : UIViewController 

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

@end 

SomeSecondClass.m

@interface SomeSecondViewController() 
…stuff 

-(void)someMethod { 

    [self.delegate doThisForMe]; 
} 

@end 

CustomClass.h

#import <UIKit/UIKit.h> 
#import 「 SomeSecondViewController.h」 

@interface MyCustomViewController : UIViewController <SomeSecondCustomViewControllerDelegate> 
//adding on <NSFileManagerDelegate> removes the warning... 
@end 

CustomClass.h

...standard stuff... 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"MySegue"]) { 

     //this is where the warning happens on "self" 
     [segue.destinationViewController setDelegate:self]; 

    } 
} 


- (void)doThisForMe { 

    //doing some stuff... 

} 
@end 

我打開了以前的項目,其中警告不存在,現在出現相同的警告。我想知道這是否是Xcode問題?

回答

12

您正在運行到引起歧義的問題在Objective-C如何找到一個匹配的選擇和處理的id參考。

UIStoryboardSegue destinationViewController返回id。然後您的代碼嘗試在此id參考上調用setDelegate方法。由於沒有關於這個id實際引用的信息,所以它不知道你可能意味着哪個setDelegate:方法(有很多)。所以編譯器掃描它所知道的列表並選擇一個。在這種情況下,它從NSFileManager類中選擇setDelegate:方法。由於self不符合NSFileManagerDelegate協議,您會收到警告。

你可以忽略這個警告,你的代碼在這種情況下可以正常工作。

更好的解決方案是通過增加投幫助編譯器:

[(SomeSecondCustomViewController *)segue.destinationViewController setDelegate:self]; 

這將讓編譯器知道哪些setDelegate:方法你真正的意思。

順便說一句 - 將NSFileManagerDelegate添加到您的班級中,即使此刻有效,也不是有效的解決方案。對某些import語句進行簡單的重新排序可能會導致編譯器做出不同的選擇,並且您的警告將會返回,但會抱怨不符合某些其他協議。

+0

僅供任何人瀏覽,這是Xcode 6中Swift兼容性的編譯器變更。向前移動Swift將期待設置代表的「as」類型。這與上述鑄造相同。我的猜測是這就是爲什麼警告只發生在Xcode 6中。 – DoS

0

儘量明確地輸入(給類型)的destinationVC,就像這樣:

SomeSecondCustomViewController *vc = (SomeSecondCustomViewController *)segue.destinationViewController; 
vc.delegate = self; 
+0

我已經這樣做了,它也會刪除警告,但在prepareForSegue期間應該是一個不必要的步驟:因爲應該已經爲您完成這些過程。在Xcode 5中,我從來沒有得到過這個錯誤,之後就是拋出一個循環。 – DoS

1

事實證明,這是Xcode 6 beta中的一個bug /更改。在Xcode 5.1.1上運行完全相同的代碼不會產生警告或錯誤。問題是因爲在Xcode 6編譯器要求類型

(id<NSFileManager>) 

代表。在Xcode 5.1中,編譯器只是簡單地期望

(id) 

代表類型。

如rmaddy在

[(SomeSecondCustomViewController *)segue.destinationViewController setDelegate:self]; 

它確實刪除警告說,鑄造類型,但是這應該是一個不必要的步驟,並且將粉筆它在Xcode的一個問題。

0

@rmaddy提供了正確的答案。對於那些輕微接受Objective-C教學的人來說,這是一個更詳細的例子。

[[segue destinationViewController] setDelegate:self]; 
    UIPopoverController *popoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 
    self.flipsidePopoverController = popoverController; 
    popoverController.delegate = self; 

到:

我從我的代碼更改

[(UIPopoverController *)segue.destinationViewController setDelegate:self]; 
    UIPopoverController *popoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 
    self.flipsidePopoverController = popoverController; 
    popoverController.delegate = self; 

和警告消失。