Auto Layout Programmatically
처음 iOS 개발을 시작할 때 UI를 구성하는 가장 좋은 방법은 storyboard
를 사용하는 것입니다. 위치를 잡기 쉽고 육안으로 확인을 할 수 있기 때문입니다. 저 역시 계속해서 storyboard
를 사용해왔습니다. 하지만 항상 모든 영상이나 블로그들의 글을 보면
“storyboard
로는 한계가 있다. 코드로 작성을 해야할 때가 있다”
사실 이 말에 크게 공감할 일이 없었습니다. 아직까지는 공부를 이제 막 시작한 저에게는 storyboard
만으로도 충분히 좋은 결과물을 볼 수 있었습니다.
하지만 협업을 할 일이 생겼고 iOS 프로젝트는 협업을 어떻게 해야하나를 알아보던 중 git
을 통해 협업을 하다보면 storyboard
의 conflict
가 상당히 많이 일어나는 것을 알게 되었고, 하나의 storyboard
파일만 사용하는 것은 옳지 않은 방법이라는 것을 알게 되었습니다.
그래서 직접 코드로 UI를 구성하고 위치시키는 것도 역시 공부를 해보아야겠다는 생각이 들었고 공부한 것을 기록하고자 이렇게 글을 작성하게 되었습니다. 이러한 주제들에 대해서 많은 글들이 있습니다. 꼭 한번 읽어보시기 바랍니다.
- iOS User Interfaces: Storyboards vs. NIBs vs. Custom Code
- Storyboard vs Programmatically in Swift
- stackoverflow - When to use Storyboard and when to use XIBs
그렇다면 오늘은 간단한 UIButton
과 UILabel
을 코드로 만들고 배치시켜보도록 하겠습니다.
1. Create UIButton
Programmatically
먼저 viewDidLoad()
안에 버튼을 하나 동적으로 생성해보도록 하겠습니다.
class ViewController:UIViewController {
let myButton = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
myButton.setTitle("This is Button", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.backgroundColor = .darkGray
self.view.addSubview(myButton)
}
}
기본적으로 버튼을 하나 생성하고 superview
에 붙여보았습니다. 하지만 실행시켜보면 버튼은 어디에도 보이지 않을 것입니다. 왜냐하면 버튼의 위치와 사이즈를 정해주지 않았기 때문입니다. 그럼 위치와 사이즈를 지정해보도록 하겠습니다.
class ViewController:UIViewController {
let myButton = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
myButton.setTitle("This is Button", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.backgroundColor = .darkGray
myButton.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
self.view.addSubview(myButton)
}
}
위와 같은 버튼은 왼쪽 상단의 끝에 위치하게 됩니다.
기본적으로 x
와 y
좌표는 좌측 상단에서부터 (0, 0)으로 시작하게 됩니다. 오른쪽 방향이 x
의 양의 방향이고, 아래쪽 방향이 y
의 양의 방향입니다. 또한 이 좌표 위치는 컴포넌트의 좌측 상단 모서리에 해당하게 됩니다. 즉 좌측 상단의 끝이 위치를 정하는 기준점이 되고 너비와 높이로 컴포넌트의 크기를 정하게 되는 것입니다.
storyboard
를 통해 버튼을 위치시킬 때도 여러분은 단순히 버튼을 올려놓기만 하지는 않을 것입니다. 다양한 디바이스에서 일관되거나 혹은 다르게 보이게 하기 위해 Constraints
를 사용하실 겁니다. 그럼 이제 우리가 만든 버튼에 Constraints
를 코드로 적용시켜보도록 하겠습니다.
2. Set constraints for UIButton
Programmatically
Constraints
를 적용하기 위해서는 일단 절대적인 위치와 크기를 정해준 코드를 지워주고 코드로 Constraints
를 적용시키기 위해서는 반드시 some_View.translatesAutoresizingMaskIntoConstraints = false
를 설정해주어야 합니다.
class ViewController:UIViewController {
let myButton = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
myButton.setTitle("This is Button", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.backgroundColor = .darkGray
self.view.addSubview(myButton)
myButton.translatesAutoresizingMaskIntoConstraints = false
}
}
기본적으로
Constraints
는superview
에 붙인 후에 작성해야합니다.
그럼 이제 본격적으로 Constraints
를 적용시켜보도록 하겠습니다.
class ViewController:UIViewController {
let myButton = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
myButton.setTitle("This is Button", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.backgroundColor = .darkGray
self.view.addSubview(myButton)
myButton.translatesAutoresizingMaskIntoConstraints = false
myButton.centerXAnchor.constraint(equalTo:view.centerXAnchor)
.isActive = true // ---- 1
myButton.centerYAnchor.constraint(equalTo:view.centerYAnchor)
.isActive = true // ---- 2
myButton.heightAnchor.constraint(equalToConstant: 200)
.isActive = true // ---- 3
myButton.widthAnchor.constraint(equalToConstant: 200)
.isActive = true // ---- 4
}
}
myButton
을superview
의x
축을 기준으로 가운데 정렬시키는 코드입니다. 반드시.isActive = true
를 해주어야 적용이 됩니다. 우리가storyboard
로 구성할 때Horizontal Alignment
와 같은 역할입니다.myButton
을superview
의y
축을 기준으로 가운데 정렬시키는 코드입니다. 우리가storyboard
로 구성할 때Vertical Alignment
와 같은 역할입니다.myButton
너비의 크기를200
으로 고정시켜주는 코드입니다.myButton
높이의 크기를200
으로 고정시켜주는 코드입니다.
코드로
Constraints
를 적용시킬 때는equalTo
, 즉 기준 고정점이 중요합니다.
이렇게 화면에 정가운데로 버튼을 위치시켜보았습니다.
3. Create UILabel
and Set constraints for UILabel
Programmatically
그렇다면 이제는 기존의 코드에 하나의 UILabel
을 코드로 만들고 myButton
아래 위치시켜보도록 하겠습니다.
class ViewController:UIViewController {
let myButton = UIButton()
let myLabel = UILabel()
override func viewDidLoad(){
super.viewDidLoad()
myButton.setTitle("This is Button", for: .normal)
myButton.setTitleColor(.white, for: .normal)
myButton.backgroundColor = .darkGray
self.view.addSubview(myButton)
myButton.translatesAutoresizingMaskIntoConstraints = false
myButton.centerXAnchor.constraint(equalTo:view.centerXAnchor)
.isActive = true
myButton.centerYAnchor.constraint(equalTo:view.centerYAnchor)
.isActive = true
myButton.heightAnchor.constraint(equalToConstant: 200)
.isActive = true
myButton.widthAnchor.constraint(equalToConstant: 200)
.isActive = true
myLabel.text = "This is My Label"
myLabel.backgroundColor = .white
self.view.addSubview(myLabel)
myLabel.translatesAutoresizingMaskIntoConstraints = false
myLabel.topAnchor.constraint(equalTo: myButton.bottomAnchor
,constant: 30).isActive = true // ---- 1
myLabel.leftAnchor.constraint(equalTo: view.leftAnchor
, constant: 40).isActive = true // ---- 2
myLabel.rightAnchor.constraint(equalTo: view.rightAnchor
, constant: -40).isActive = true // ---- 3
}
}
myLabel
을myButton
의 밑 변을 기준으로 30만큼 아래로 위치시키는 코드입니다. 즉myButton
의 30만큼 아래에myLabel
을 위치시키는 코드입니다.myLabel
을superview
의 왼쪽 변을 기준으로 40 만큼 떨어뜨려 놓는 코드입니다.myLabel
을superview
의 오른쪽 변을 기준으로 –40 만큼 떨어뜨려 놓는 코드입니다. 여기서 –40인 이유는x
좌표의 양의 방향은 오른쪽이기 때문에 오른쪽에서 40만큼 왼쪽으로 떨어뜨려놓기 위해서는 –40을 사용해야합니다.
4. Add Action to UIButton
우리가 storyboard
로 버튼을 생성하고 이를 ViewController
로 연결시키면 자동으로 클릭에 대한 액션이 설정됩니다. 하지만 코드로 버튼을 생성한다면 이러한 과정까지 직접해주어야 합니다.
그렇다면 버튼을 눌렀을 때 Alert
창이 뜨는 액션을 만들어보도록 하겠습니다.
class ViewController:UIViewController{
/*
code
*/
override func viewDidLoad(){
super.viewDidLoad()
/*
code
*/
myButton.addTarget(self, action: #selector(btnClicked),
for: .touchUpInside)
}
@objc func btnClicked(){
let alert = UIAlertController(title: "Click!"
, message: "You clicked that button"
, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Confirm"
, style: .default , handler: nil))
present(alert, animated: true, completion: nil)
}
}
마무리
오늘은 이렇게 간단하게 UIButton
과UILabel
을 코드로 만들고 위치시켜보는 것을 해보았습니다. 이렇게 코드로 Constraints
를 적용시킬 때 다음의 두 가지의 코드는 반드시 작성해주셔야 합니다.
some_View.translatesAutoresizingMaskIntoConstraints = false
.isActive = true
그리고 Constraints
의 종류에는 storyboard
로 적용시킬 때와 마찬가지로 많은 종류가 존재합니다. 다음의 링크를 통해 어떤 종류가 있는지 반드시 숙지해놓으시면 많은 도움이 되실 것입니다.
Working With Auto Layout and Layout Anchors
다음에는 보다 복잡하고 동적인 화면을 코드로 작성해보는 시간을 갖도록 하겠습니다. 감사합니다.
Source : https://github.com/ehdrjsdlzzzz/ios_constraints_programmatically/tree/master/Practice1
참고자료