2012-12-10 56 views
0

我有一個名爲DataManager的單例類。這個類被其他幾個類用來處理加載和保存plist文件。Objective C:在前向聲明VS解析問題中找不到屬性問題:預期的A類型

我正在添加DataManager保存截圖以及plist文件的功能。這需要我加載我希望截圖的視圖。我正在加載的視圖來自導入DataManager的控制器。

顯然,這是循環依賴,所以我用:

@class GardenView; 

然而,這導致瞭如下錯誤:

  • 接收機「花園景觀」類消息是前向聲明
  • 接收器類型'GardenView'例如消息是正向
  • 聲明在前向類中找不到屬性'邊界'
  • 對象園景'財產「層」不能向前 類對象中找到「園景」

這似乎是無法找到的屬性從UIView的超類繼承。這是前瞻性類聲明的真實情況嗎?

如果我使用標準#進口,而不是@class,我得到:

  • 解析問題:預期A型

在園景引用廠(其中我只是導入方法精):

- (void) addPlantToView: (Plant*) plant; 
- (void) addPlantToGarden: (Plant*) plant; 
- (void) addPlantToViewAndGarden: (Plant*) plant; 

植物類並導入DataManager的,但如果我把它改爲@class,我得到:

  • 沒有已知的類方法選擇「sharedDataManager」

,這是什麼問題,該如何解決?類方法在頭文件(+ sharedDataManager)中。我在做一些完全錯誤的事情嗎?

回答

3

你還沒有明確說明你在做什麼,進口vs @class。我認爲這造成了混亂。這裏有你想要做什麼:

  • 在GardenView.h,使用@class Plant
  • 在Plant.h,使用@class GardenView
  • 在GardenView.m,使用#import "Plant.h"
  • 在Plant.m,使用#import "GardenView.m"

這打破了標題中的循環依賴關係,但仍允許實現查看依賴類的完整信息。

現在爲什麼@class單是不夠的原因是因爲所有@class Foo所做的就是告訴編譯器「有一個名爲Foo類」,不告訴它什麼都有關的類。編譯器不知道它的方法。它不知道它的超類。它所知道的是,如果它看到令牌Foo,那麼它代表一個類的類型。你可以在頭文件中使用它,這樣你就可以在參數和返回類型中引用這個類,但是爲了實際做任何類型的值,你仍然需要完整的#import。但是,您可以毫無問題地將。#import放在.m文件中。

你需要#import而不是@class在你的頭的唯一情況是,如果你想從有問題的類繼承。你不能繼承前向聲明的類,所以你需要完整的#import。當然,如果您需要訪問在相同頭文件中定義的其他類型(例如結構體,枚舉等),您也可能需要#import,但在obj-c中不太常見。

+0

這個伎倆!謝謝!我認爲所有import/@類聲明必須位於頭文件中,並且.m文件中的唯一導入是對其自己頭的引用。謝謝! – Jenny

+0

@珍妮:不。所有'#import'的確是複製並粘貼引用文件的內容來代替'#import'行(它也會檢查頭是否已經被導入過,如果已經導入過,就什麼也不做)。它不同於'#include')。如果可以將代碼包含在多個翻譯單元(閱讀:源文件)中,您甚至可以將代碼放在.h中,儘管這很少見。 –

+0

「你只需要在標題中使用#import而不是@class,這是因爲你想從所討論的類繼承。」謝謝,沒有意識到這一點。 – guptron