아까 공부하러 간다고 말씀을 드렸습니다만.. 오늘의 공부는 바로 iOS(Xcode-Swift)공부였습니다. ㅋㅋㅋ
iOS개발을 하다보면 가끔 특정 View에서만 화면을 회전해야하는 경우가 있습니다.
예를들어 가로->세로->가로로 하나의 화면을 세로로 보여야한다던가,
세로->가로->세로 등의 화면으로 보여줘야한다는 등 특정한 요구가 있는 경우가 있습니다.
그런 경우 코드로 어떻게 처리를 하는지를 알아보겠습니다.
특히 제가 사용하는 소스의 경우 UINavigationController가 적용된 UIViewController에서 강제적으로 화면을 회전시키는 소스입니다.
뭐, 다른 방법이 있을 수 있으나..(supportedInterfaceOrientations를 이용해 변경을 해보려했는데 잘 되지 않더군요. 저의 방법이 잘못된거일지도 모르겠지만, 대략적인 느낌은 전역으로 지정된 UINavigationController 혹은 제가 커스텀한 CustomUIViewController가 override된 supportedInterfaceOrientations를 무시하는 것 같았습니다.)
한동안 삽질을 하던 저는 이 방법을 통해 해결하였습니다.
(더 좋은 방법이 있다면 알려주시면 감사하겠습니다! 감사히 배우겠습니다!!)
우선 이 코드를 이해하기 위해서는 viewWillAppear 함수와 viewWillDisappear 함수에 대해 대강 이해하고 계셔야합니다.
이 함수들을 이해하기 위해서는 View Controller의 생명주기에 대해서 알고 계셔야 이해가 쉬운데요.
이 부분은 나중에 다시한번 다루도록 하겠습니다. (... 시간관계상)
간단히 말하면 viewWillAppear 함수와 viewWillDisappear 함수는 뷰의 생명주기에 있어 뷰가 나타날때, 뷰가 사라질때 사용(Override)하는 함수입니다. (짤막..)
네.. 지금은 뷰의 생명주기를 알려드리는 시간은 아니니 대강 그렇다는것만 이해하시면 그나마 이해하시는데 큰 문제는 없을겁니다.
바로 소스를 보시죠
화면을 시작할 때 회전시키기 (가로 회전 혹은 세로 회전)
override func viewWillAppear(_ animated: Bool) {
// 화면 회전하기 (가로 회전)
let orientation = UIInterfaceOrientation.landscapeRight.rawValue
// 세로로 회전 (주석제거)
// let orientation = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(orientation, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
}
화면이 종료될 때 원상복귀시키기 (세로->가로->세로 혹은 가로->세로->가로)
override func viewWillDisappear(_ animated: Bool) {
// 기존 세로에서 가로로 변경했었다면 다시 세로로 원상복구
let orientation = UIInterfaceOrientation.portrait.rawValue
// 기존 가로에서 세로로 변경했었다면 다시 가로로 원상복구 (주석제거)
// let orientation = UIInterfaceOrientation.landscapeRight.rawValue
UIDevice.current.setValue(orientation, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
}
보시면 크게 어려운 건 없습니다.
세로모드 혹은 가로모드의 값을 orientation 변수에 담아서
UIDevice 클래스에 접근하여 Value, Key 형태로 저장해줍니다.
그리고 attemptRotationToDeviceOrientation함수에서 새로운 인터페이스 방향을 수동으로 적용해줍니다.
UIDevice - Use aUIDeviceobject to get information about the device such as assigned name, device model, and operating-system name and version.
대충 UIDevice 객체는 디바이스의 정보를 가져오는 용도로 사용할 수 있다는 모양입니다.
다들 아시다시피 UINavigationController 클래스도 UIViewController를 상속하여 만들어진 클래스입니다.
그러다보니 UINavgiationController만의 함수가 아닌 상속되어진 UIViewController에도 있는것으로 보입니다.
단지 제 생각이지만, 제가 supportedInterfaceOrientations 함수를 사용함에 있어서 계속해서 실패한 까닭은 이러한 상속여부에 따라 UIViewController에서는 Override가 적용이 불가하지 않았나 싶네요. (쉽게말해 무시)
UINavigationController.attemptRotationToDeviceOrientation - If your view controller does this, when those conditions change, your app should call this class method.The system immediately attempts to rotate to the new orientation.
대충 ViewController에서 상태의 변경이 필요한 경우 해당 메소드를 부르면 사용자가 원하는 새로운 방향으로 즉각적으로 회전을 시도한다는 모양입니다.
우선 안드로이드에서 사용하는 버튼을 보이거나 보이지 않게하는 방법입니다. (setVisibility함수 사용)
Android에서 사용하는 방법(Java)
private Button btn_test
//init
btn_test = findViewById(R.id.btn_test);
//버튼을 보이지 않게
btn_test.setVisibility(View.INVISIBLE);
//버튼을 보이게
btn_test.setVisibility(View.VISIBLE);
iOS에서는 @IBOutlet으로 Storyboard에서 간단하게 드래그로 변수 선언을 해주시고, layer의 isHidden을 이용해 컨트롤합니다.
iOS에서 사용하는 방법입니다.(Swift5)
@IBOutlet weak var btn_test: UIButton!
//버튼 보이지 않게
btn_test.layer.isHidden = true
//버튼 보이게
btn_test.layer.isHidden = false
단, 위 코드는 UIBarButtonItem 컴포넌트에서는 먹히지 않습니다. (layer가 선언이 되는 컴포넌트는 전부 가능 - Button, View 등)
컴포넌트가 UIBarButtonItem인 경우(Swift5)
@IBOutlet weak var navigation_btn_test: UIBarButtonItem!
//버튼 보이지 않게
navigation_btn_test.isEnabled = false
navigation_btn_test.tintColor = UIColor.clear
//버튼 보이게
navigation_btn_test.isEnabled = true
navigation_btn_test.tintColor = UIColor.black
UIBarButtonItem 컴포넌트의 경우 아무래도 isHidden을 사용할 수 없는 모양입니다.
(객체 내에서 Hidden을 시킬 수 있는 함수나 멤버가 없는 모양)
따라서 위의 소스는
1. 버튼을 사용하지 못하게 막음.
2. 색상을 없애버려 없는 버튼처럼 만들어 줌.
두가지를 이용했다고 보시면 됩니다.
단, 이는 제가 아직 부족한 부분이 많아서 다른 좋은 방법이 있을 수 있으므로, 좋은 방법이 있다면 업데이트 해두도록 하겠습니다.
(소스의 표현방식은 각양각색이니까요!)
테스트 장비 : 맥미니(2020)
버전정보 (v1.0)
- v1.0 2020.07.01 배포
* 저작권에 위반될 수 있는 컨텐츠(이미지, 동영상 등)나 게시글은 삭제되거나 수정될 수 있습니다.
* 문제의 여지가 될 수 있는 컨텐츠의 경우 댓글 달아 주시면 빠른 시일 내에 조치하도록 하겠습니다.
* Karzin은 항상 공부중입니다. 설명이 틀리거나 잘못된 부분이 있다면 의견내주시는대로 수정하도록 하겠습니다.