// sender로 선택할 경우
@IBAction func test1(_ sender: Any) {
}
// None으로 선택할 경우
@IBAction func test2() {
}
// Sender and Event로 설정할 경우
@IBAction func test3(_ sender: Any, forEvent event: UIEvent) {
}
@IBAction func sliderChanged(_ sender: Any) {
}
@objc func action(_ sender: Any){
print(#function)
}
override func viewDidLoad() {
super.viewDidLoad()
// Method를 selector로 변경해주기
let sel = #selector(action(_:))
btn.addTarget(self, action: sel, for: .touchUpInside)
}
}
action_: 가 뭔가??
@IBAction func report(_ sender: UIButton) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.stateLabel.text = sender.state.debugString
}
}
@IBAction func stateChanged(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex{
case 0:
btn.isEnabled = true
btn.isSelected = false
btn.isHighlighted = false
case 1:
btn.isHighlighted.toggle()
case 2:
btn.isSelected.toggle()
case 3:
btn.isEnabled = false
default:
break
}
report(btn)
}
※ https://zeddios.tistory.com/513 - (DispatchQueue)
class TextButtonViewController: UIViewController {
@IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
//btn은 text와 textcolor를 아래와 같이 변경할 수 없다.
// btn.titleLabel?.text = "Hello"
// btn.titleLabel?.textColor = .systemRed
// for 아래는 state를 말하는 것이다.
btn.setTitle("Hello", for: .normal)
btn.setTitle("Haha", for: .highlighted)
btn.setTitleColor(.systemRed, for: .normal)
btn.titleLabel?.backgroundColor = .systemYellow
}
}
class ImageButtonViewController: UIViewController {
@IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let normalImage = UIImage(named: "plus-normal")
let highlightedImage = UIImage(named: "plus-highlighted")
btn.setImage(normalImage, for: .normal)
btn.setImage(highlightedImage, for: .highlighted)
//btn.setBackgroundImage(<#T##image: UIImage?##UIImage?#>, for: <#T##UIControl.State#>)
}
}
Picker View를 생성해주고 아래와 같이 datasource와 delegate을 연결해 준다.
그리고 아래와 같이 UIPickerViewDataSource 프로토콜을 만족해야된다.
extension TextPickerViewController: UIPickerViewDataSource{
// pickerview의 column은 몇개인가?
func numberOfComponents(in pickerView: UIPickerView) -> Int {
}
// pickerview에는 몇개의 element가 들어가는가?
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
}
}
class TextPickerViewController: UIViewController {
let devTools = ["Xcode", "Postman", "SourceTree", "Zeplin", "Android Studio", "SublimeText"]
let fruits = ["Apple", "Orange", "Banana", "Kiwi", "Watermelon", "Peach", "Strawberry"]
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension TextPickerViewController: UIPickerViewDataSource{
// 몇개의 componenet인가?(column)
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return devTools.count
}
}
extension TextPickerViewController: UIPickerViewDelegate{
// 어떤 글자를 나타낼 것인가? pickerview는 위에서부터 index 0이라고 한다.
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return devTools[row]
}
// 선택될 경우 함수가 실행이 된다.
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(devTools[row])
}
}
만약 numberOfComponents의 return 값을 2로하면 아래와 같아진다.
report Action을 설정하여 현재 지목하고 있는 pickerview의 값을 print한다.
@IBAction func report(_ sender: Any) {
// inComponent는 컬럼의 index이다. 즉 0이면 맨 왼쪽 column이다.
let row = picker.selectedRow(inComponent: 0)
guard row >= 0 else {
print("not found")
return
}
print(devTools[row])
}
class ImagePickerViewController: UIViewController {
lazy var images: [UIImage] = {
return (0...6).compactMap { UIImage(named: "slot-machine-\($0)") }
}()
}
extension ImagePickerViewController: UIPickerViewDataSource{
// 항목의 column을 몇개로 할 것인가?
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// 한 컬럼에는 몇개의 component를 넣어줄 것인가? -> 반복해서 componenet를 보여주는 것이 가능
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return images.count * 3
}
}
/////////// 이해가 잘 안됨 /////////////
// View를 재 사용하기!
extension ImagePickerViewController: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
// 만약 마지막 Parameter가 imageview인지 확인하기
if let imageView = view as? UIImageView{
imageView.image = images[row % images.count]
return imageView
}
// 재 사용할 imageview가 없다면 Imageview를 만들어서 사용하기
let imageView = UIImageView()
imageView.image = images[row % images.count]
imageView.contentMode = .scaleAspectFit
return imageView
}
}
// pickerView에 설정된 높이
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 60
}
@IBAction func shuffle(_ sender: Any?) {
let firstIndex = Int.random(in: 0..<images.count) + images.count
let secondIndex = Int.random(in: 0..<images.count) + images.count
let thirdIndex = Int.random(in: 0..<images.count) + images.count
// pickerView에 있는 특정 로우를 선택할 때는 selectRow를 사용한다.
picker.selectRow(firstIndex, inComponent: 0, animated: true)
picker.selectRow(secondIndex, inComponent: 1, animated: true)
picker.selectRow(thirdIndex, inComponent: 2, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// touchEvent를 비활성화 해주기
picker.isUserInteractionEnabled = false
picker.reloadAllComponents()
shuffle(nil)
}
먼저 scrollView를 datasource와 delegate으로 이어주기
아래와 같이 pageControl을 설정해줄 수 있다. UI로 tint color와 current page를 설정해 줄 수 있다.
아래와 같이 코드로 pagecontrol을 설정할 수 있다.
@IBOutlet weak var pager: UIPageControl!
@IBOutlet weak var listCollectionView: UICollectionView!
let list = [UIColor.red, UIColor.green, UIColor.blue, UIColor.gray, UIColor.black]
override func viewDidLoad() {
super.viewDidLoad()
// pages를 List의 숫자로 설정하기
pager.numberOfPages = list.count
// 첫 화면의 page를 첫번째꺼로 설정하기
pager.currentPage = 0
//pager의 색깔을 변경해주기
pager.pageIndicatorTintColor = UIColor.systemGray3
pager.currentPageIndicatorTintColor = UIColor.systemRed
}
※ https://sweethoneybee.tistory.com/49 -contentOffset
// page를 넘기면 pagecontrol도 넘어가게 하기
extension PageControlViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let width = scrollView.bounds.size.width
let x = scrollView.contentOffset.x + (width / 2.0)
let newPage = Int(x / width)
if pager.currentPage != newPage {
pager.currentPage = newPage
}
}
}
먼저 아래와 같이 action을 설정해준다.
// pageControl을 탭하는 순간 page가 한개씩 넘어가게 설정해보기
@IBAction func pageChanged(_ sender: UIPageControl) {
let indexPath = IndexPath(item: sender.currentPage, section: 0)
listCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
lass SimpleSliderViewController: UIViewController {
@IBOutlet weak var redSlider: UISlider!
@IBOutlet weak var greenSlider: UISlider!
@IBOutlet weak var blueSlider: UISlider!
// valueChange로 action을 설정하기
@IBAction func sliderChanged(_ sender: Any) {
// 슬라이더의 현재 값을 가져오기
let r = CGFloat(redSlider.value)
let g = CGFloat(greenSlider.value)
let b = CGFloat(blueSlider.value)
let color = UIColor(red: r, green: g, blue: b, alpha: 1.0)
// view의 background를 위에 설정한 color로 설정하기
view.backgroundColor = color
}
override func viewDidLoad() {
super.viewDidLoad()
redSlider.value = 1.0
greenSlider.value = 1.0
blueSlider.value = 1.0
redSlider.minimumValue = 0.0
redSlider.maximumValue = 1.0
}
}
class CustomSliderViewController: UIViewController {
@IBOutlet weak var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// slider를 커스텀 이미지로 설정해보기
let img = UIImage(systemName: "lightbulb")
slider.setThumbImage(img, for: .normal)
// track의 tintcolor를 설정해보기
slider.minimumTrackTintColor = UIColor.systemRed
slider.maximumTrackTintColor = UIColor.black
}
}
class NonContinuousSliderViewController: UIViewController {
@IBOutlet weak var valueLabel1: UILabel!
@IBOutlet weak var slider1: UISlider!
@IBOutlet weak var valueLabel2: UILabel!
@IBOutlet weak var slider2: UISlider!
@IBAction func sliderChanged1(_ sender: UISlider) {
valueLabel1.text = String(format: "%.1f", sender.value)
}
@IBAction func sliderChanged2(_ sender: UISlider) {
valueLabel2.text = String(format: "%.1f", sender.value)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
아래와 같이 segmented control을 추가해주고, segments를 3으로 설정하면 3개의 segment가 생성이된다.
그리고 아래와 같이 segments를 구성해준다.(title을 변경하기)
Label을 segmented Control을 통하여 alignment를 변경해보자
아래와 같이 SegmentedControl을 outlet으로 추가하고, alignmentControl의 segement Index를 textAlignment의 rawvalue로 설정을 해준다.
@IBOutlet weak var label: UILabel!
@IBOutlet weak var alignmentControl: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
// 초기 정렬을 초기 Label의 정렬에 맞추기
alignmentControl.selectedSegmentIndex = label.textAlignment.rawValue
}
}
// value Changed -> sender의 index로 rawValue를 받는다. 아니면 그냥 .center로
@IBAction func alignmentChanged(_ sender: UISegmentedControl) {
label.textAlignment = NSTextAlignment(rawValue: sender.selectedSegmentIndex) ?? .center
}
↓ ViewDidLoad에 아래의 코드를 추가한다.
momentarySwitch.isOn = alignmentControl.isMomentary
@IBAction func toggleMomentary(_ sender: UISwitch) {
alignmentControl.isMomentary = sender.isOn
}
alignmentControl.setTitle("왼쪽", forSegmentAt: 0)
↓ 아래와 같이 insert action 코드를 추가하자.
@IBAction func insertSegment(_ sender: Any) {
// 먼저 title에 값이 들어갔는 지, guard를 통하여 확인하기
guard let title = titleField.text, title.count > 0 else {
return
}
segmentedControl.insertSegment(withTitle: title, at: segmentedControl.numberOfSegments, animated: true)
titleField.text = nil
}
↓ 아래와 같이 delete action 코드를 추가하자.
@IBAction func removeSegment(_ sender: Any) {
// for 문을 통하여 segment 한 개 한 개씩 확인하기.
guard let title = titleField.text, title.count > 0 else {
return
}
for index in 0..<segmentedControl.numberOfSegments {
if let currentTitle = segmentedControl.titleForSegment(at: index), currentTitle == title {
segmentedControl.removeSegment(at: index, animated: true)
}
break
}
titleField.text = nil
}
override func viewDidLoad() {
super.viewDidLoad()
let normalImage = UIImage(named: "segment_normal")
let selectedImage = UIImage(named: "segment_selected")
// segment의 background를 설정하기
segmentedControl.setBackgroundImage(normalImage, for: .normal, barMetrics: .default)
segmentedControl.setBackgroundImage(selectedImage, for: .selected, barMetrics: .default)
var img = UIImage(named: "segment_normal_normal")
print(img?.size)
segmentedControl.setDividerImage(img, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
let halfWidth = (img!.size.width - 20) / 3.0
var offset = UIOffset(horizontal: halfWidth, vertical: 0.0)
segmentedControl.setContentPositionAdjustment(offset, forSegmentType: .left, barMetrics: .default)
img = UIImage(named: "segment_normal_selected")
segmentedControl.setDividerImage(img, forLeftSegmentState: .normal, rightSegmentState: .selected, barMetrics: .default)
img = UIImage(named: "segment_selected_normal")
segmentedControl.setDividerImage(img, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
}
Switch의 attribute을 아래와 같이 설정을 하면
아래와 같이 switch의 UI가 변하게 된다.
그리고 switch 위에 imageview는 아래와 같이 highlighted일 경우를 설정해주자.
아래와 같이 switch를 누를 때에 highlight의 boolean값을 변경하고 싶으면 아래와 같이 action을 추가해준다.
@IBOutlet weak var bulbImageView: UIImageView!
@IBOutlet weak var testSwitch: UISwitch!
// switch Action
@IBAction func stateChanged(_ sender: UISwitch) {
bulbImageView.isHighlighted = sender.isOn
}
override func viewDidLoad() {
super.viewDidLoad()
testSwitch.isOn = bulbImageView.isHighlighted
}
@IBAction func toggle(_ sender: Any) {
testSwitch.setOn(!testSwitch.isOn, animated: true)
stateChanged(testSwitch)
}
아래와 같이 storyboard를 구성하자
아래와 같이 outlet을 설정해주자.
class StepperViewController: UIViewController {
@IBOutlet weak var valueLabel: UILabel!
@IBOutlet weak var valueStepper: UIStepper!
@IBOutlet weak var autorepeatSwitch: UISwitch!
@IBOutlet weak var continuousSwitch: UISwitch!
@IBOutlet weak var wrapSwitch: UISwitch!
// stepper가 바뀌면 valuelabel의 text값이 해당값으로 바뀌게 설정하기
@IBAction func valueChanged(_ sender: UIStepper) {
valueLabel.text = "\(sender.value)"
}
// 사용자가 꾹 누르는 것을 허용을 할 것인가?
@IBAction func toggleAutorepeat(_ sender: UISwitch) {
valueStepper.autorepeat = sender.isOn
}
// 꾹 누르고 있으면 바로 올라가는게 아니라 touch event가 다 끝나고 결과값이 변하게 된다.
@IBAction func toggleContinuous(_ sender: UISwitch) {
valueStepper.isContinuous = sender.isOn
}
// true일 경우 최댓값을 도달 후 최솟값으로 바꿔준다.
@IBAction func toggleWrap(_ sender: UISwitch) {
valueStepper.wraps = sender.isOn
}
override func viewDidLoad() {
super.viewDidLoad()
autorepeatSwitch.isOn = valueStepper.autorepeat
continuousSwitch.isOn = valueStepper.isContinuous
wrapSwitch.isOn = valueStepper.wraps
}
}
↓ 아래와 같이 outlet과 action이 설정이되어있다.
class ActivityIndicatorViewViewController: UIViewController {
@IBOutlet weak var hiddenSwitch: UISwitch!
@IBAction func toggleHidden(_ sender: UISwitch) {
}
@IBAction func start(_ sender: Any) {
}
@IBAction func stop(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
@IBOutlet weak var loader: UIActivityIndicatorView!
class ActivityIndicatorViewViewController: UIViewController {
@IBOutlet weak var loader: UIActivityIndicatorView!
@IBOutlet weak var hiddenSwitch: UISwitch!
// 토글 스위치를 설정해주기
@IBAction func toggleHidden(_ sender: UISwitch) {
loader.hidesWhenStopped = sender.isOn
}
// activity indicator 시작하기
@IBAction func start(_ sender: Any) {
if !loader.isAnimating{
loader.startAnimating()
}
}
@IBAction func stop(_ sender: Any) {
if loader.isAnimating {
loader.stopAnimating()
}
}
override func viewDidLoad() {
super.viewDidLoad()
hiddenSwitch.isOn = loader.hidesWhenStopped
// loader.isAnimating = true
loader.startAnimating()
}
}
class ProgressViewViewController: UIViewController {
// progressView outlet 생성하기
@IBOutlet weak var progress: UIProgressView!
// setProgress를 사용하여 80프로까지 차는 애니메이션 구현하기
@IBAction func update(_ sender: Any) {
progress.setProgress(0.8, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// 초기 프로그레스 값은 0.0
progress.progress = 0.0
progress.trackTintColor = UIColor.systemGray
progress.progressTintColor = .systemRed
}
}