2013-08-22 54 views
1

我對我所理解的Objective-C中指針和引用的使用方式的基本錯誤。我一直在尋找這個問題,調整我的代碼等等,但都無濟於事。Objective-C中的基本指針/引用問題 - 一個實例中的訪問器方法影響所有類級別的實例

我知道我在做一個簡單的錯誤的地方(新手的Objective-C,而不是OOP)只是我沒有看到它......哎呀:P

我歡迎任何和所有輸入從你們自己的更聰明的角度來看。 :)

如果我可以說明我的問題,它是這樣的:

在我「的main.m」文件我實例化一個特定的「矩形」類的4種獨立的情況下,每一個獨特的尺寸和笛卡爾座標可以通過getter(s)/ setter(s)訪問。 合成「寬度」和「高度」屬性,而座標包裝在可通過自定義方法訪問的對象(XYPpoint類)內。

當我訪問寬度和高度屬性時,我能夠爲任何和所有實例獲取/設置唯一值,但是當我嘗試使用座標時,我不可避免地最終會同時更改所有實例的所有實例。

我在做什麼錯?我可以看到,我的起源對象僅實例化了1個(而不是4個),但我不明白爲什麼?!?

* * *編輯: 按hamstergene的友好建議(見1日回答)我又試了一次,得到它通過聲明*原點爲@property工作。不過,我還必須首先@synthesize它,然後在@implementation中覆蓋它。我不知道爲什麼,但這似乎有點像矯枉過正。這是正確的方式嗎?此外Xcode中似乎不喜歡它,並拋出一個警報(編譯仍然雖然)


至於這裏的代碼是(短):

========== ================================================== ======================

(接口,用於包裝類的座標的對象)

// XYPoint.h 
// 

#import <Foundation/Foundation.h> 

@interface XYPoint : NSObject 

@property float x, y; 

-(void) setX: (float) xVal andY: (float) yVal; 

@end 

======= ================================================== ====================== ===

(實施包裝類的座標的對象)

// XYPoint.m 
// 

#import "XYPoint.h" 

@implementation XYPoint 

@synthesize x, y; 

-(void) setX: (float) xVal andY: (float) yVal { 
    x = xVal; 
    y = yVal; 
} 

@end 

========================== ================================================== ======

(接口爲我的Rectangle類)

// Rectangle.h 
// 

#import <Foundation/Foundation.h> 
#import "XYPoint.h" 

@interface Rectangle : NSObject 

@property float width, 
        height; 

-(XYPoint *) origin; 
-(void)   setWidth: (float) w andHeight: (float) h; 
-(void)   setOrigin: (XYPoint *) pt; 
-(void)   printData; 

@end 

========================== ================================================== ======

(實施我的Rectangle類)

// Rectangle.m 
// 

#import "Rectangle.h" 

@implementation Rectangle 

@synthesize width, height; 

XYPoint *origin; 

-(void) setWidth:(float) w andHeight: (float) h { 
    width = w; 
    height = h; 
} 

-(XYPoint *) origin { 
    return origin; 
} 

-(void) setOrigin: (XYPoint *) pt { 

    if (! origin) { 
     NSLog(@"origin object created"); 
     origin = [ [ XYPoint alloc ] init ]; 
    } 
    origin.x = pt.x; 
    origin.y = pt.y; 
} 

-(void) printData { 
    NSLog(@"origin coordinates (%.1f, %.1f)", origin.x, origin.y); 
    NSLog(@"Width = %.1f, Height = %.1f\n"); 
} 

@end 

================================== ================================================

(和最後的main.m)

// main.m 
// 

#import "Rectangle.h" 

int main(int argc, const char * argv[]) { 

    @autoreleasepool { 

     XYPoint  *rect1Origin = [ [ XYPoint alloc ] init ]; 
     XYPoint  *rect2Origin = [ [ XYPoint alloc ] init ]; 
     XYPoint  *rect3Origin = [ [ XYPoint alloc ] init ]; 
     XYPoint  *rect4Origin = [ [ XYPoint alloc ] init ]; 
     Rectangle *rect1   = [ [ Rectangle alloc ] init ]; 
     Rectangle *rect2   = [ [ Rectangle alloc ] init ]; 
     Rectangle *rect3   = [ [ Rectangle alloc ] init ]; 
     Rectangle *rect4   = [ [ Rectangle alloc ] init ]; 

     [ rect1Origin setX: 200 andY: 420 ]; 
     [ rect1 setOrigin: rect1Origin ]; 
     [ rect1 setWidth: 250 andHeight: 75 ]; 
     NSLog(@"1st Rectangle\n------------------------------------------"); 
     [ rect1 printData ]; 

     [ rect2Origin setX: 400 andY: 300 ]; 
     [ rect2 setOrigin: rect2Origin ]; 
     [ rect2 setWidth: 100 andHeight: 180 ]; 
     NSLog(@"2nd Rectangle\n------------------------------------------"); 
     [ rect2 printData ]; 

     [ rect3Origin setX: 99 andY: 99 ]; 
     [ rect3 setOrigin: rect3Origin ]; 
     [ rect3 setWidth: 50 andHeight: 450 ]; 
     NSLog(@"3rd Rectangle\n------------------------------------------"); 
     [ rect3 printData ]; 

     [ rect4Origin setX: 20 andY: 100 ]; 
     [ rect4 setOrigin: rect4Origin ]; 
     [ rect4 setWidth: 10 andHeight: 3 ]; 
     NSLog(@"4th Rectangle\n------------------------------------------"); 
     [ rect4 printData ]; 

     NSLog(@"\n------------------------------------------"); 
     NSLog(@"1st Rectangle again...\n------------------------------------------"); 
     [ rect1 printData ]; 

     NSLog(@"2nd Rectangle again...\n------------------------------------------"); 
     [ rect2 printData ]; 

     NSLog(@"3rd Rectangle again...\n------------------------------------------"); 
     [ rect3 printData ]; 

     NSLog(@"4th Rectangle again...\n------------------------------------------"); 
     [ rect4 printData ]; 

     NSLog(@"\n\n********* All rects have the same coordinates why does this happen?"); 

    } 
    return 0; 
} 

================================== ================================================

OUTPUT

origin object created 
1st Rectangle 
------------------------------------------ 
origin coordinates (200.0, 420.0) 
Width = 250.0, Height = 75.0 

2nd Rectangle 
------------------------------------------ 
origin coordinates (400.0, 300.0) 
Width = 100.0, Height = 180.0 

3rd Rectangle 
------------------------------------------ 
origin coordinates (99.0, 99.0) 
Width = 50.0, Height = 450.0 

4th Rectangle 
------------------------------------------ 
origin coordinates (20.0, 100.0) 
Width = 10.0, Height = 3.0 

------------------------------------------ 
1st Rectangle again... 
------------------------------------------ 
origin coordinates (20.0, 100.0) 
Width = 250.0, Height = 75.0 

2nd Rectangle again... 
------------------------------------------ 
origin coordinates (20.0, 100.0) 
Width = 100.0, Height = 180.0 

3rd Rectangle again... 
------------------------------------------ 
origin coordinates (20.0, 100.0) 
Width = 50.0, Height = 450.0 

4th Rectangle again... 
------------------------------------------ 
origin coordinates (20.0, 100.0) 
Width = 10.0, Height = 3.0 


********* All rects have the same coordinates why does this happen? 
+0

爲了什麼它的價值,這些類(實際結構)已經存在於CoreGraphics。看看CGPoint和CGRect –

+0

謝謝詹姆斯。構建這些類實際上是我正在閱讀的這本書的一部分(Steve Kochan的「Objective-C中的編程」):) –

回答

0

我發現我做錯了什麼。使用@ property/@綜合指令工作正常,但從技術上講,問題是一個簡單的語法問題,改變了我的Rectangle.m實現中變量*原點的範圍。

基本上所有我需要做的是包住彎引號的變量聲明

所以基本上,而不是這個(沒有他們我是無意中設置*原點爲全局性的。):

//=======================================  
@implementation Rectangle  
//=======================================  

@synthesize width, height;  

XYPoint *origin; 

我應該這樣做:

//======================================= 
@implementation Rectangle 
//======================================= 
{ 
XYPoint *origin; 
} 

@synthesize width, height; 

Et瞧 - '問題解決了。感謝大衛託德(來自:http://classroomm.com/objective-c/index.php?topic=9389.0)爲他的解決方案(並再次hamstergene和rob mayoff在這裏)

3

XYPoint *origin;是一個全局變量,這意味着它在整個程序中共享。您需要將其聲明爲屬性,就像您使用x,y,widthheight所做的一樣。

+0

刪除全局變量聲明,刪除自定義getter和setter,添加'@ property'和'@合成條款。 – hamstergene

+1

或者只是將它變成一個實例變量(「ivar」)。 –

+0

再次感謝hamstergene和rob。是否有一個原因,我需要綜合*起源,然後覆蓋它,而不是隻使用自定義getter/setters(即不合成屬性)? –