2014-03-19 25 views
0

作爲新的客觀-C編碼我開始寫一個基本的應用程序,完全以編程方式(不使用故事板或XIB)在一個文件中,我AppViewController H和M文件。 一切工作可愛。UIPicker查看子類的工作不IOS

於是我就想通過繼承的部分分手的代碼質量,並且一切順利除了UIPickerView。其實簡單地註釋掉[background addSubview:colorPicker];似乎完全解決這個問題。我從來沒有在網上找到答案,所以我開始製作一份新文件來複制上述問題。 所以這裏有雲:

UIPickerViewController.h


#import <UIKit/UIKit.h> 
#import "Picker.h" 
@interface UIPickerViewController : UIViewController 
@end 

僅需輸入我的新類。

UIPickerViewController.m

#import "UIPickerViewController.h" 
@interface UIPickerViewController() 
@end 

@implementation UIPickerViewController 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    UIView *superview = self.view; 
    int height = superview.bounds.size.height; 
    int width = superview.bounds.size.width; 
    CGRect popupRect = CGRectMake(0, 0, width, height); 
    UIView *popup = [[UIView alloc]initWithFrame:popupRect]; 
    popup.tag = 8; 
    [superview addSubview:popup]; 
    Picker *picker = [[Picker alloc]initWithFrame:popupRect]; 
    [picker viewAddTypeScreenToView:superview]; 
} 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
} 
@end 

建立與標籤(這樣我可以與我的新階級隨後參考) 然後行動從我的新類的方法來填充我的新的新觀點視圖。

Picker.h


#import <UIKit/UIKit.h> 

@interface Picker : UIView 
<UIPickerViewDataSource,UIPickerViewDelegate> 
{ 
    UIPickerView *colorPicker; 
    NSMutableArray *colorsArray; 
} 

@property (nonatomic, retain) UIPickerView *colorPicker; 
@property (nonatomic, retain) NSMutableArray *colorsArray; 
@property (strong,nonatomic) UILabel *myValue; 

-(void)viewAddTypeScreenToView:(UIView*)superview; 

@end 

設置我的變量和使用方法。

Picker.m


#import "Picker.h" 

@implementation Picker 

@synthesize colorsArray; 
@synthesize colorPicker; 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
    } 
    return self; 
} 


-(void)viewAddTypeScreenToView:(UIView*)superview 
{ 
    UIView *baseView =[superview viewWithTag:8]; 

    int height = baseView.bounds.size.height; 
    int width = baseView.bounds.size.width; 

    CGRect fullScreen = CGRectMake(0, 0, width, height); 
    UIView *background = [[UIView alloc]initWithFrame:fullScreen]; 
    background.backgroundColor = [UIColor blackColor]; 

    colorsArray = [[NSMutableArray alloc] initWithObjects:@"Red",@"Blue",@"Yellow",@"Green",nil]; 

    CGRect myPickerRect = CGRectMake(10, 70, (width/2)-40, 200); 
    colorPicker = [[UIPickerView alloc]initWithFrame:myPickerRect]; 
    colorPicker.dataSource = self; 
    colorPicker.delegate = self; 
    colorPicker.showsSelectionIndicator = YES; 
    [colorPicker selectRow:2 inComponent:0 animated:YES]; 

    CGRect labelFrame = CGRectMake(10, 10, 180, 50); 
    _myValue = [[UILabel alloc]initWithFrame:labelFrame]; 
    _myValue.textColor = [UIColor redColor]; 
    _myValue.text = @"select colour"; 
    [background addSubview:_myValue]; 
    [background addSubview:colorPicker]; 
    [baseView addSubview:background]; 

} 



-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ 
    return 1; 
} 

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ 
    return colorsArray.count;; 
} 

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component 
{ 
    return colorsArray[row]; 
} 

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{ 
    _myValue.text = [NSString stringWithString:colorsArray[row]]; 
} 

@end 

最後由選擇器類文件的方法稱爲啓動。 這給了我沿着這些線路

-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000 
2014-03-19 10:29:48.407 Briefcase[1800:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000' 

這是我讀過的是無論是數據源,或ARC系統做了一個錯誤,但是,沒有,我已經找到了應對的涉及或工作用的類型設置我以上。我確信這是一件非常簡單的事情,但經過幾天搜索失敗後,它正式讓我發瘋。

回答

0

問題很可能是UIPickerViewController中正在創建的Picker實例永遠不會添加到視圖層次結構中,從而提前發佈(假設我們在此討論使用ARC的項目)。

這導致pickerview的委託和數據源變得無效,並且基本上在任何隨機對象指向。這就是導致你崩潰的原因:你的委託信息無法傳遞,因爲委託已經死亡。選擇器仍然保留着一個指針,該指針用於指向委託,但它現在已變得無效並指向一個隨機對象,在這種情況下,它是一個表視圖單元,它基本上不知道如何處理此消息並崩潰。

如果添加選擇器*選擇器作爲一個實例變量或保留/強大的屬性UIPickerViewController的問題就會消失。h - 這將使選擇器保持超出viewDidLoad方法的範圍,並應保持活動狀態。

但這只是一個解決方法,真正的問題是您的整體設計。你說你對objective-c是新手,事實上,你看起來對iOS視圖和視圖控制器層次結構缺乏基本的瞭解,並且在某種程度上缺乏面向對象編程的概念。在嘗試修復代碼之前,您可能需要深入瞭解一些更基本的內容,因爲坦率地說,它應該被重寫而不是固定。

我很樂意爲您提供有關如何構建代碼的建議,但請提供一些關於您希望首先實現哪些功能的信息。

編輯(響應您的評論):

  • 作爲一個經驗法則,不要過度幾類,除非必要的傳播功能。對於服務於相當基礎設施目標的對象,如專門的文本字段或pickerview,總是問自己:「如果我想在另一個項目中重用該對象,是否會像使用任何其他現有對象一樣簡單,如for例如,UILabel?「如果答案是「否」,那麼有些事情是錯誤的。理想情況下,接口對象是自包含的,要使用它們,只需調用它們,將它們添加到視圖並告訴它們,要顯示哪些文本或提供哪些選項。如果這些信息可能會發生變化,或者如果對象需要與代碼的其他部分進行交互,請使用委託和協議。在任何情況下,你的對象的功能都不應該與硬編碼值相關聯,或者依賴某種觀點來獲得某個標籤。

  • 如果您繼承UIView,那麼生成的對象應該像UIView的任何其他實例一樣工作。它應該由你或某個對象添加到視圖層次結構中,但不應該添加或刪除它自己。如果它在沒有被添加到視圖層次結構的情況下工作,那麼有些事情是錯誤的。視圖的作用是成爲界面的一部分,它所包含的所有邏輯都應該爲此而努力,而不是更多,而不是更少。

  • 通常情況下,接口對象不應該互相干擾。如果某個對象發生了某些事情(按下按鈕,選擇了選項,文本改變了......),並且另一個對象應該反映該變化,則視圖控制器負責實現此目的。視圖控制器是邏輯發生的地方。如果有一項任務需要大量複雜的邏輯,那麼將該邏輯封裝到目標構建類中可能是個好主意。一個這樣的例子是管理網絡連接的類。這個類應該再次自成一體:如果視圖控制器需要一些遠程信息,它會詢問你的網絡類。一旦你的網絡類有這樣的信息(或無法檢索它),它會報告給你的視圖控制器。視圖控制器然後更新接口 - 在任何情況下,聯網類應該包含影響接口的代碼。

重要的是要明白,你可以很好地忽略這些規則,仍然最終與一個工作的應用程序。在某些情況下,「直接」方式看起來更容易實施,因此看起來很誘人。但是稍後你會付出代價 - 一旦你開始調試你的代碼。如果你的選擇器不符合它的要求,那麼你需要查看幾個地方,並圍繞幾個對象進行思考,以使一個接口對象正確行事。並且可能會在修復其他功能的同時破壞一個功能。

所以,儘量讓它從一開始就做對,儘管它需要更多的規劃和學習。相信我,它付出了代價,我幾年前就像你一樣開始;)

+0

這確實解決了問題! 我在UIPickerViewController.h中添加了Picker * picker作爲類變量,並修改了UIPickerViewController.m文件中的調用以適應此 - 並且我們又回到了遊戲中! 在我的實際項目中,我有一個projectVC,它爲Left,Mid和Right列和一個空的彈出視圖導入uiview類 - 全部添加爲子視圖。 左列有一個按鈕,用於啓動彈出方法,該方法寫入先前添加的彈出視圖(標記8)。 如果有更好的解決方法,它會很樂意在船上。這是我們如何學習的正確:) –

+0

正確:)請參閱我更新的答案,瞭解一些經驗法則。如果您需要了解更多信息,請告訴我們! – Toastor

+0

非常感謝您的建議。這一切都採取了船上。所以在這種情況下,我會更好地將viewcontroller類中的所有代碼保留原來的樣子,而不是試圖將項目分解成可管理的塊? 我有一個NSObject類存儲SQL數據和方法來檢查數據庫,插入,更新,選擇和刪除任何通用的SQL相關的調用。在我的整個項目中,我相信這是唯一遵循您所提建議的課程:P –