2014-03-19 6 views
0

객관적인 C 코딩에 익숙해지면서, 하나의 파일에 내 AppViewController h 및 m 파일로 완전히 프로그래밍 방식으로 (스토리 보드 또는 xib를 사용하지 않고) 기본 앱을 작성하기 시작했습니다. 모든 것이 멋지게 작동했습니다.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의 대리자와 데이터 소스가 무효화되고 기본적으로 임의의 임의의 개체를 가리키게됩니다. 그게 당신의 사고의 원인입니다. 대의원이 이미 사망했기 때문에 귀하의 대의원에게 메시지를 전달할 수 없습니다. 피커는 여전히 대리자를 가리키는 데 사용되는 포인터를 유지하지만 무효화되고 무작위 개체 (이 경우 테이블 뷰 셀)를 가리키며 이는 기본적으로이 메시지로 무엇을해야할지 알지 못하고 충돌합니다.

Picker * picker를 ivar로 추가하거나 UIPickerViewController에/strong 속성을 추가하면 문제가 없어집니다.h -이 선택 도구는 viewDidLoad 메서드의 범위를 벗어나 유지하며 계속 살아 있어야합니다.

하지만 이는 단지 일시적인 해결책 일뿐 실제 문제는 전반적인 디자인입니다. 당신은 객관성에 대해 새롭다 고 말했고 실제로 iOS보기와 컨트롤러 계층 구조에 대한 기본적인 이해가 부족하고 어느 정도는 객체 지향 프로그래밍의 개념이있는 것으로 보입니다. 솔직히 말해서 코드를 고치려고 시도하기 전에 좀 더 기본적인 것을 파고 드는 것이 좋을 수도 있습니다.

코드를 구조화하는 방법에 대한 제안을 기꺼이 제공 하겠지만 먼저 달성하고자하는 기능에 대한 정보를 제공해주십시오. (귀하의 코멘트에 응답)

편집 : 엄지 손가락의 규칙으로

  • 가 필요한 경우가 아니면 여러 클래스를 통해 기능을 확산하지 않습니다. 전문 텍스트 필드 나 피커 뷰 (pickerview)와 같은 다소 인프라가 필요한 객체의 경우 항상 다음과 같이 스스로에게 물어보십시오. "다른 프로젝트에서 해당 객체를 다시 사용하려면 다른 기존 객체를 사용하는 것만 큼 쉽습니다. 예, UILabel? " 대답이 "아니오"이면, 무엇인가 잘못되었습니다. 이상적으로 인터페이스 객체는 자체 포함되어 있으며이를 사용하기 위해 인터페이스 객체를 호출하고 뷰에 추가하고 표시 할 텍스트 또는 제공 할 옵션을 알려줍니다. 해당 정보가 변경 될 수 있거나 개체가 코드의 다른 부분과 상호 작용해야하는 경우 위임 및 프로토콜을 사용하십시오. 어떤 상황에서도 개체의 기능이 하드 코딩 된 값에 묶여 있거나 특정 태그가있는보기에 의존해서는 안됩니다.

  • UIView를 하위 클래스로 만들면 결과 개체는 다른 UIView 인스턴스처럼 동작해야합니다. 사용자 또는 일부 오브젝트에 의해 뷰 계층 구조에 추가되어야하지만 자체를 추가하거나 제거해서는 안됩니다. 뷰 계층 구조에 전혀 추가하지 않고 작동하면 문제가 발생합니다. 보기는 사용자 인터페이스의 일부가되는 목적을 위해 제공되며, 포함 된 모든 논리는 그 이상으로, 더 적지 않고 그 목적을 위해 작동해야합니다.

  • 일반적으로 인터페이스 개체는 서로 간섭해서는 안됩니다. 하나의 오브젝트 (버튼이 눌려지고, 옵션이 선택되고, 텍스트가 변경된 경우)에 어떤 일이 발생하고 다른 오브젝트가 그 변경을 반영한다고 가정하면,이를 수행하는 것은 뷰 컨트롤러의 책임입니다. 뷰 컨트롤러는 로직이 발생하는 장소입니다. 복잡한 로직을 많이 필요로하는 태스크가 있다면, 그 로직을 목적 빌드 클래스에 캡슐화하는 것이 좋습니다. 이러한 예는 네트워크 연결을 관리하는 클래스입니다. 이 클래스는 다시 포함되어야합니다.보기 컨트롤러가 원격 정보를 필요로하는 경우 네트워크 클래스에 요청합니다. 네트워크 클래스가 해당 정보를 갖거나 검색하지 못하면보기 컨트롤러로 다시보고합니다. 그런 다음보기 컨트롤러는 인터페이스를 업데이트합니다. 네트워킹 클래스에 인터페이스에 영향을주는 코드가 포함되어 있으면 안됩니다.

이러한 규칙을 무시하고 여전히 작동중인 앱으로 끝낼 수 있음을 이해하는 것이 중요합니다. 그리고 어떤 경우에는 "직접적인"방법이 구현하기 쉽고 매우 유혹적으로 보일 수 있습니다. 하지만 나중에 코드를 디버깅하기 시작하면 가격을 지불하게됩니다. 선택기가 정상적으로 동작하지 않으면 몇 개의 개체를 조사하고 여러 개체 주위에 마음을 감싸고 하나의 인터페이스 개체가 올바르게 작동하도록해야합니다. 그리고 다른 기능을 수정하면서 한 기능을 중단 할 가능성이 있습니다.

더 많은 계획과 학습이 필요하지만 처음부터 바로 시도해보십시오. 저를 믿으십시오, 그것은 지불합니다, 나는 당신 같이 다만 몇 년 시작했다;)

+0

이것은 참으로 문제점을 고쳤다! Picker * picker를 UIPickerViewController.h의 클래스 변수로 추가하고이를 수용하기 위해 UIPickerViewController.m 파일에서 호출을 수정했습니다. 우리는 다시 게임에 참가했습니다! 실제 프로젝트에서 왼쪽, 중간 및 오른쪽 열 및 빈 팝업보기에 대한 uiview 클래스를 가져 오는 projectVC가 있습니다. 모두 하위 뷰로 추가되었습니다. 왼쪽 열에는 이전에 추가 한 팝업보기 (태그 8)에 쓰는 팝업 방법을 시작하는 버튼이 있습니다. 더 좋은 방법이있는 경우 기꺼이 탑승합니다. 이것은 우리가 올바르게 배우는 방법입니다. –

+0

Right :) 엄지 손가락 규칙에 대한 업데이트 된 답변을 확인하십시오. 그리고 더 많이 알 필요가 있으면 알려주세요! – Toastor

+0

조언을 주셔서 대단히 감사합니다. 그것은 모두 타고 있습니다. 따라서이 경우 프로젝트를 관리 가능한 덩어리로 분해하려고 시도하지 않고 viewcontroller 클래스에 모든 코드를 그대로 두는 것이 낫습니다. 데이터베이스를 검사하고 삽입, 업데이트, 선택 및 일반 SQL 관련 호출을 삭제하는 SQL 데이터 및 메서드를 저장하는 NSObject 클래스가 있습니다. 내 전체 프로젝트에서 나는 이것이 당신이 주어진 조언을 따르는 유일한 클래스라고 생각합니다 : P –