簡體   English   中英

UIPicker View子類化無法運行IOS

[英]UIPicker View subclassed not working IOS

我是Objective-C編程的新手,我AppViewController用一個文件(我的AppViewController h和m文件)完全以編程方式(而不使用情節提要或xib)編寫一個基本應用程序。 一切都很好。

因此,我想通過子節細分代碼的數量,所有內容與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系統有關的,但是我發現的任何響應都與我上面的設置類型無關或不相關。 我敢肯定這確實很簡單,但經過幾天的搜索失敗后,這正式使我發瘋。

問題很可能是在UIPickerViewController中創建的Picker實例永遠不會添加到視圖層次結構中,因此會過早地發布(假設我們在這里討論的是使用ARC的項目)。

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

如果將Picker * picker作為ivar或UIPickerViewController.h的保留/強屬性添加,此問題應會消失-這將使Picker超出viewDidLoad方法的范圍,並應使其保持活動狀態。

但這只是一種解決方法,真正的問題是您的總體設計。 您說過您對Objective-C並不陌生,的確,您似乎對iOS視圖和視圖控制器層次結構缺乏基本了解,並且在某種程度上缺乏面向對象編程的概念。 在嘗試修復代碼之前,您可能想研究更基本的東西,因為坦率地說,應該重寫而不是修復代碼。

我們很樂意為您提供有關如何構建代碼的建議,但請提供一些有關您首先要實現的功能的信息。

編輯(根據您的評論):

  • 根據經驗,除非必要,請勿將功能分散在多個類上。 對於具有相當基礎結構目的的對象(例如專用文本字段或pickerview),請始終問自己:“如果我想在另一個項目中重用該對象,那么就像使用任何其他現有對象一樣容易,例如例如UILabel?” 如果答案為“否”,則說明有問題。 理想情況下,接口對象是獨立的,要使用它們,您只需調用它們,將它們添加到視圖中,然后告訴它們要顯示的文本或提供的選項。 如果該信息可能會更改,或者對象需要與代碼的其他部分進行交互,請使用委托和協議。 在任何情況下,都不應將對象的功能綁定到硬編碼值或依賴於某些視圖來具有特定標簽。

  • 如果將UIView子類化,則所得對象的行為應與UIView的任何其他實例相同。 應該由您或某個對象將其添加到視圖層次結構中,但不應添加或刪除自身。 如果該方法完全不添加到視圖層次結構中,則說明存在問題。 視圖的目的是成為您的界面的一部分,該視圖所包含的所有邏輯都應為此目的而工作,而不是更多,更少。

  • 通常,接口對象不應相互干擾。 如果一個對象發生了某些事情(按下按鈕,選擇了選項,文本已更改...),而另一個對象應該反映了這一變化,則視圖控制器有責任做到這一點。 視圖控制器是發生邏輯的地方。 如果存在需要大量復雜邏輯的任務,則最好將該邏輯封裝到目標構建類中。 這樣的例子就是管理網絡連接的類。 該類應該再次自包含:如果視圖控制器需要一些遠程信息,它將詢問您的網絡類。 一旦您的網絡類獲得了該信息(或檢索失敗),它就會向您的視圖控制器報告。 然后,視圖控制器將更新接口-在任何情況下,網絡類都不應包含影響接口的代碼。

重要的是要了解,您很可能會忽略這些規則,但最終仍可以使用可運行的應用程序。 在某些情況下,“直接”方式可能更易於實現,因此看起來很誘人。 但是,您將在以后開始調試代碼時付出代價。 如果選擇器的行為不盡如人意,則需要查看多個位置並將您的思維包裹在多個對象上,只是使一個接口對象的行為正確即可。 而且很可能您會在修復另一個功能時破壞其中一個功能。

因此,即使需要更多的計划和學習,也應嘗試從一開始就做對。 相信我,它付了錢,幾年前我就和你一樣開始了;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM