위 사진과 같이 키 윈도우에 피커뷰를 올려보니 할 것도 많고 삽질도 많이 해서 정리.
일단 키윈도우 안에 피커뷰만 올리면 닫을 수가 없다.
-키 윈도우 안에 피커뷰 올리기 소스
먼저 클래스에 아래와 같이 <UIPickerViewDataSource, UIPickerViewDelegate> 추가
@interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
클래스안에 지속적으로 사용할 변수들 선언
{
NSArray* filmName;
UIPickerView* pickerView;
UIActionSheet* actionSheet;
}
viewDidLoad함수 안에 피커뷰에서 사용할 array선언
filmName=[[NSArray alloc]initWithObjects:@"e1",@"e2",@"e3",@"e4",@"e5",@"e6",@"e7",@"e8",@"e9",@"e10",@"e11", nil];
@"" 안에 원하는 이름을 적고 , 로 구분하면 된다.
피커뷰가 뜨기 원하는 위치에 아래와 같이 소스 추가
pickerView=[[UIPickerView alloc]init]; //피커뷰 초기화
[pickerView setDelegate:self]; //Delegate, dataSource 자신(위의 클래스 명 옆에 명시해둠)
[pickerView setDataSource:self];
UIWindow* keyWindow=[[UIApplication sharedApplication]keyWindow]; //키윈도우 가져오기
//키 윈도우 안에 들어갈 피커뷰 크기설정
[pickerView setFrame:CGRectMake(0.0f, keyWindow.frame.size.height-pickerView.frame.size.height,
keyWindow.frame.size.width,
pickerView.frame.size.height)];
[keyWindow addSubview:pickerView]; //키 윈도우에 피커뷰 추가
피커뷰를 사용하려면 아래와 같은 함수들이 필요
//컴포넌트 수, 세로로 구분되는 갯수
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
//각 컴포넌트 별로 몇 개의 줄을 사용할 것인가 정하는 메소드
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [filmName count]; //파일네임객체 갯수 반환
}
//선택한 row에 따라 할 작업
-(void)pickerView:(UIPickerView *)mypickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch(row)
{
case 0: //첫번째 선택
//할일
break;
default: //설정안되는 부분이긴 하지만 아무것도 해당하지 않을 때의 경우
//할일
break;
}
}
//각 행에 들어갈 이름
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [filmName objectAtIndex:row]; //파일네임의 각 객체의 이름 반환
}
위와 같이 작업하면 피커뷰를 만드는 작업을 여러번 할 시 계속 생성되는 문제가 있다.
(본인은 버튼에 할당해서 버튼 클릭할 때마다 피커뷰가 실행이 되었다.)
이를 해결하기 위해 BOOL변수를 통해 작업을 해주었다.
먼저 클래스 변수에 BOOL isPicker; 선언
//생성 시
if(!isPicker)
{
pickerView=[[UIPickerView alloc]init]; //피커뷰 초기화
[pickerView setDelegate:self]; //Delegate, dataSource 자신(위의 클래스 명 옆에 명시해둠)
[pickerView setDataSource:self];
keyWindow=[[UIApplication sharedApplication]keyWindow];//키 윈도우 가져오기
//키 윈도우 안에 들어갈 피커뷰 크기설정
[pickerView setFrame:CGRectMake(0.0f, keyWindow.frame.size.height-pickerView.frame.size.height,
keyWindow.frame.size.width,
pickerView.frame.size.height)];
[keyWindow addSubview:pickerView]; //키 윈도우에 피커뷰 추가
}
//피커뷰 없애는 함수
-(void)closePicker
{
pickerView.hidden=YES;
pickerView=nil;
isPicker=NO;
}
위와 같이 작업하면 깔끔하게 없앨 수 있다.
- 피커뷰 위에 버튼을 두어 이를 통해 피커뷰를 없애고 싶어 액션시트를 통해 작업
먼저 클래스 변수에 액션시트 변수 추가
UIActionSheet* actionSheet;
//생성 시
actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"" destructiveButtonTitle:nil otherButtonTitles:nil]; //액션시트 생성
CGRect pickerFrame = CGRectMake(0, 30, 320, 300);//피커뷰크기 x,y, width, height y값 띄운 이유는 위가 짤려서
// 액션 시트 확인 버튼을 포함하고 있는 툴바를 만들어 준다
UIToolbar* toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 43)];
// 만들어진 툴바의 스타일을 투명한 검정으로 설정하고 사이즈를 맞게 조절한다.
toolBar.barStyle = UIBarStyleBlackOpaque;
[toolBar sizeToFit];
// 닫기 버튼을 추가해 준다. 확인 버튼의 스타일은 파란 close 버튼이고 확인 버튼을 누르면 Selector에 있는 closeBtnPressed 메서드가 실행된다.
UIBarButtonItem* doneBtn=[[UIBarButtonItem alloc]initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeBtnPressed:)];
// Toolbar에 들어갈 리스트를 위해 배열을 만들어 주고 배열안에는 확인 버튼을 넣는다. 그 후 툴바에 setItems 메서드를 사용해 버튼을 포함시킨다
NSArray *tempArray = [[NSArray alloc]initWithObjects:doneBtn, nil];
[toolBar setItems:tempArray animated:YES];
tempArray=nil;
// PickerView를 만들어주고 델리게이트를 설정해 주고 인디케이터를 YES로 함으로서 선택된 행에 하이라이트가 됨을 설정할 수 있다.
pickerView = [[UIPickerView alloc]initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator=YES;
//Delegate, dataSource 자신(위의 클래스 명 옆에 명시해둠)
pickerView.delegate=self;
pickerView.dataSource=self;
// 액션 시트에 툴바와 피커 뷰를 포함시키고, 키 윈도우 안에 엑션시트를 포함 시킨다
[actionSheet addSubview:pickerView];
[actionSheet addSubview:toolBar];
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
//엑션시트위치 및 크기 설정
[actionSheet setBounds:CGRectMake(0, 0, 320, 410)];
- 닫기버튼클릭 시 동작하는 함수 추가
//닫기버튼 함수
-(void)closeBtnPressed:(id)sender
{
[actionSheet dismissWithClickedButtonIndex:1 animated:YES];
}
위와 같이 추가해주면 맨 위의 사진같이 피커뷰를 사용할 수 있다.
- 에러내역
액션 시트 생성 시 위와 같이 쓰지 않고
actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle: nil destructiveButtonTitle:nil otherButtonTitles:nil]; //액션시트 생성
위와 같이 nil로 적으면 실행 시
위와 같은 에러가 난다.
위 에러는 먼저 그리거나, 사이즈가 맞지 않을 때 생성되는 오류라고 한다.
그에 따라 디버그 모드로 따라가보니
//엑션시트위치 및 크기 설정
[actionSheet setBounds:CGRectMake(0, 0, 320, 410)];
위 부분에서 에러가 나, 이리저리 바꾸어 보았지만 해결되지 않았다.
그래서 빨강색의 nil을 @""으로 변경하니 동작하였다.
(꼭 cancel버튼이 아닌 타이틀이나 destructive버튼 타이틀을 @""으로 바꾸어도 동작잘한다. ios7기준으로 destructive버튼 타이틀을 @""으로 바꾸는게 가장 괜찮은거 같다. 다 nil처리하면 액션시트가 없는게 되어서 그려러나.. 다 nil이면 걍 init이나 똑같을거 같은데 이것도 한번 테스트. 에러 똑같이 난다... )
- 추천 해결법
이는 애플문서를 보면 "UIActionSheet is not designed to be subclassed, nor should you add views to its hierarchy."
와 같이 적혀있다.
위와 같이 사용하는 걸 권하지 않는 다는 뜻이다.
이에 대해 StackOverflow를 찾아보니
Alternative solutions:
- Create your own view and present it modally - I made a simple example project showing one way to do this.
- https://github.com/gpambrozio/BlockAlertsAnd-ActionSheets (no update for iOS 7 yet)
위와 같은 두가지 방법으로 프로그램을 짜는 것이 더 맞다는 것 같다.
클릭 시 피커뷰 대신에 네이게이션바가 있는 테이블 뷰를 띄우고
그것을 선택 시 원래 뷰의 내용이 바뀌는 방향으로 프로그래밍 하였다.
며칠간 삽질한 것과 더 좋은 내용에 대해서 찾아볼 수 있어 보람찼다.
'프로그래밍 > iOS' 카테고리의 다른 글
[ios]아이콘 (0) | 2015.04.08 |
---|---|
[ios] @property (0) | 2015.04.08 |
[ios] CGBitmapContextCreate에서 KCGImageAlphaPremultipliedFirst 사용 시 워닝 (0) | 2015.04.08 |
[ios]Category is implementing a method which will also be implemented by its primary class (0) | 2015.04.08 |
[ios] performSelector 사용 시 leak 경고 (0) | 2015.04.08 |