Cocoa Touch 프레임워크와 UIKit, Foundation

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Cocoa Touch 프레임워크란?

iOS 애플리케이션 개발 환경으로, 애플리케이션의 다양한 기능 구현에 필요한 여러 프레임워크를 포함하는 최상위 레벨의 프레임 워크

  • macOS 애플리케이션 제작에 사용하는 프레임워크
  • 핵심 프레임워크인 UIKitFoundation을 포함

UIKit 프레임워크란?

iOS 애플리케이션의 사용자 인터페이스를 구현하고 이벤트를 관리하는 프레임워크

  • 제스처처리, 애니메이션, 그림 그리기, 이미지 처리, 텍스트 처리 등 사용자 이벤트 처리를 위한 클래스를 포함
  • 테이블 뷰, 슬라이더, 버튼, 텍스트필드, 얼럿 창 등 애플리케이션의 화면을 구성하는 요소를 포함
  • UIKit 클래스 중 UIResponder에서 파생된 클래스나 사용자 인터페이스 관련된 클래스는 애플리케이션 메인 스래드에서만 사용
  • UIKit는 iOS와 tvOS플랫폼에서 사용

UIKit 기능별 요소

사용자 인터페이스

  • View and Control: 화면에 콘텐츠 표시
  • View Controller: 사용자 인터페이스 관리
  • Animation and Haptics: 애니메이션과 햅틱을 통한 피드백 제공
  • Window and Screen: 뷰 계층을 위한 윈도우 제공

사용자 액션

  • Touch, Press, Gesture: 제스처 인식기를 통한 이벤트 처리 로직
  • Drag and Drop: 화면 위에서 드래그 앤 드롭 기능
  • Peek and Pop: 3D 터치에 대응한 미리 보기 기능
  • Keyboard and Menu: 키보드 입력을 처리 및 사용자 정의 메뉴 표기

생각해보기 새롭게 ViewController를 생성하면 상단에 ‘import UIKit’이 기본적으로 명시되어있는걸 본적 있다
왜 ViewController와 UIKit는 단짝일까요?

내가 생각한 답
기본적으로 UIKit는 iOS 사용자 인터페이스를 구현하는 프레임워크이다. 사용자 인터페이스를 관리하는 View Controller를 건들기 위해서는 기본적으로 이를 관리하는 프레임워크인 UIKit가 import되어야 한다고 생각한다.

Foundation

원시 데이터타입(String, Int, Double), 컬렉션 타입(Array, Dictionary, Set) 및 운영체제 서비스를 사용해 애플리케이션의 기본적인 기능을 관리하는 프레임워크

  • 데이터타입, 날짜 및 시간 계산, 필터 및 정렬, 네트워킹 등의 기본 기능 제공
  • 프레임워크에서 정의한 클래스, 프로토콜 및 데이터 타입은 iOS뿐 아니라 macOS, watchOS, tvOS등 모든 애플 SDK에서 사용

Foundation에서 제공하는 데이터타입 및 컬렉션 타입의 대부분은 Objective-C 언어의 기능에서 지원하지 않는 것이기 때문에 언어기능을 보완하기 위한 구현이며, Swift에서는 이에 해당하는 데이터 타입과 기능 대부분을 Swift표준 라이브러리에서 제공한다.

Foundation 기능별 요소

기본

  • Number, Data, String: 원시 데이터 타입 사용
  • Collection: Array, Dictionary, Set등과 같은 컬렉션 타입 사용
  • Data and Time: 날짜와 시간을 계산하거나 비교하는 작업
  • Unit and Measurement: 물리적 차원을 숫자로 표현 및 관련 단위 간 변환 기능
  • Data Formmating: 숫자, 날짜, 측정값 등을 문자열로 변환 또는 반대 작업
  • Filter and Sorting: 컬렉션의 요소를 검사하거나 정렬하는 작업

애플리케이션 지원

  • File System: 파일 또는 폴더를 생성하고 읽고 쓰는 기능 관리
  • Archives and Serialization: 속성목록, JSON, 바이너리 파일들을 객체로 변환 또는 반대작업 관리
  • iCloud: 사용자의 iCloud 계정을 이용해 데이터를 동기화하는 작업 관리

네트워킹

  • URL Loading System: 표준 인터넷 프로토콜을 통해 URL과 상호작용하고 서버와 통신하는 작업
  • Bonjour: 로컬 네트워크를 위한 작업

생각해보기. 새롭게 ViewController 파일을 생성하면 상단에 ‘import UIKit’이 기본적으로 명시되어있다. 그렇다면 어떤 파일을 생성하면 ‘import Foundation’이 기본적으로 명시되어있을까요?

내가 생각한 답
원시 데이터 타입 및 컬렉션 타입을 사용하기 위해 기본적인 Swift파일을 생성할때 import Foundation이 된다. UIKit 내부에도 Foundation이 들어있지만, 이를 분리해서 import를 하는 이유는 iOS의 디자인 패턴인 MVC 모델을 생성할 때 사용자 인터페이스와 비즈니스 로직을 분리하기 위해 데이터 타입에서 쓰이는 Foundation을 쓰도록 권장한 것이 아닐까 싶다.

swift UIButton, UISlider, UILabel

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


UIButton, UISlider, UILabel

애플리케이션 화면을 구현할 때 자주 사용하는 UI요소들이다.

UIButton

사용자의 상호작용(터치/탭 등의 이벤트)에 반응해 미리 지정된 코드를 실행하는 컨트롤 요소

버튼 생성의 3단계

  1. 버튼을 생성하고 버튼의 유형을 선택
  2. 버튼을 나타내기 위한 문자(타이틀)을 입력하거나, 이미지를 설정한 뒤 크기를 조정
  3. 버튼에 특정 이벤트가 발생할 때 작동할 하나 이상의 메서드를 연결

버튼과 메서드 연결하는 방법

  1. addTarget(_:action:for:) 메서드 사용
  2. 인터페이스 빌더에서 연결 (@IBAction)

이때 버튼과 연결되는 메서드 형식은 아래와 같다.

func doSomething()
func doSomething(sender: UIButton)
func doSomething(sender: UIButton, forEvent event: UIEvent)

버튼의 상태: default, highlighted, focused, selected, disabled

버튼의 상태는 조합된 상태일 수 있다. 예) [default + highlighted], [selected + disabled] 등등
버튼 생성 시 기본 상태 값은 default이며, 사용자가 버튼과 상호작용을 하면 상태 값이 변하게 된다.

그리고, 프로그래밍 방식 혹은 인터페이스 빌더를 이용해 버튼의 각 상태에 대한 속성을 별도로 지정할 수 있습니다. 만약 별도로 속성을 지정하지 않으면 UIButton 클래스에서 제공하는 기본 동작을 사용하게 된다. 예) disabled 버튼은 일반적으로 흐리게 표시되며 사용자가 탭 해도 highlighted 되지 않는다.

버튼의 프로퍼티 값을 설정하는 방식에는 코드를 이용하는 방법과 스토리보드의 인스팩터를 이용하는 방법이 있다.

enum UIButtonType: 버튼의 유형

버튼의 유형에 따라 버튼의 기본적인 외형과 동작이 달라진다. 처음 버튼을 생성할 때

  1. init(type:) 메서드를 이용 혹은
  2. 인터페이스빌더의 “Attribute Inspector”에서 버튼 유형을 지정할 수 있다

이때 한번 생성된 버튼의 유형은 이후 변경 할 수 없으며, 가장 많이 사용하는 유형은 CustomSystem이지만 필요에 따라 다른 유형(Detail Disclosure, Info Light, Info Dark, Add Contact)를 사용할 수 있다.

  • var titleLabel: UILabel?: 버튼 타이틀 레이블
  • var imageView: UIImageView?: 버튼의 이미지 뷰
  • var tintColor: UIColor!: 버튼 타이틀과 이미지의 틴트 컬러

버튼의 주요 메서드

// 특정 상태의 버튼의 문자열 설정
func setTitle(String?, for: UIControlState)

// 특정 상태의 버튼의 문자열 반환
func title(for: UIControlState) -> String?

// 특정 상태의 버튼 이미지 설정
func setImage(UIImage?, for: UIControlState)

// 특정 상태의 버튼 이미지 반환
func image(for: UIControlState) -> UIImage?

// 특정 상태의 백그라운드 이미지 설정
func setBackgroundImage(UIImage?, for: UIControlState)

// 특정 상태의 백그라운드 이미지 반환
func backgroundImage(for: UIControlState) -> UIImage?

// 특정 상태의 문자열 색상 설정
func setTitleColor(UIColor?, for: UIControlState)

// 특정 상태의 attributed 문자열 설정
func setAttributedTitle(NSAttributedString?, for: UIControlState)

UILabel

한줄 또는 여러줄의 텍스트를 보여주는 뷰로, UIButton등의 컨트롤의 목적을 설명하기 위해 사용하는 경우가 많다.

레이블 생성의 3단계

  1. 레이블을 생성
  2. 레이블이 표시할 문자열을 제공
  3. 레이블의 모양 및 특성을 설정

레이블 주요 프로퍼티

var text: String? // 레이블이 표시할 문자열, 문자열이 모두 동일한 속성(폰트, 색상, 기울임꼴 등)으로 표시됩니다.
// text 프로퍼티에 값을 할당하면 attributedText 프로퍼티에도 똑같은 내용의 문자열이 할당됩니다.

var attributedText: NSAttributedString? :  // 레이블이 표시할 속성 문자열
// NSAttributed 클래스를 사용한 속성 문자열 중 특정 부분의 속성을 변경할 수 있다([예] 일부 글자 색상 변경/일부 글자 폰트 변경)
// attributedText 프로퍼티에 값을 할당하면 text 프로퍼티에도 똑같은 내용의 문자열이 할당

var textColor: UIColor! :  // 문자 색상
var font: UIFont!:  // 문자 폰트

var textAlignment: NSTextAlignment:  // 문자열의 가로 정렬 방식으로 left, right, center, justified, natural 중 하나를 선택

var numberOfLines: Int:  // 문자를 나타내는 최대 라인 수
// 문자열을 모두 표시하는 데 필요한 만큼 행을 사용하려면 0으로 설정, 기본 값은 1
// 설정한 문자열이 최대 라인 수를 초과하면 lineBreakMode 프로퍼티의 값에 따라 적절히 잘라서 표현
adjustsFontSizeToFitWidth  // 프로퍼티를 활용하면 폰트 사이즈를 레이블의 넓이에 따라 자동으로 조절해줌

var baselineAdjustment: UIBaselineAdjustment  // 문자열이 Autoshrink 되었을 때의 수직 정렬 방식

Align Baseline  // 문자가 작아졌을 때 기존 문자열의 기준선에 맞춤
Align Center  // 문자가 작아졌을 때 작아진 문자의 중앙선에 맞춤
None  // 문자가 작아졌을 때 기존 문자열의 위쪽 선에 맞춤

var lineBreakMode: NSLineBreakMode  // 레이블의 경계선을 벗어나는 문자열에 대응하는 방식

Character wrap  // 여러 줄 레이블에 주로 적용되며, 글자 단위로 줄 바꿈을 결정
Word wrap  // 여러 줄 레이블에 주로 적용되며, 단어 단위로 줄 바꿈을 결정

Truncate head  // 한 줄 레이블에 주로 적용되며, 앞쪽 텍스트를 자르고 ...으로 표시
Truncate middle  // 한 줄 레이블에 주로 적용되며, 중간 텍스트를 자르고 ...으로 표시
Truncate tail  // 한 줄 레이블에 주로 적용되며, 끝쪽 텍스트를 자르고 ...으로 표시, 기본 설정 값임

UISlider

연속된 값 중에서 특정 값을 선택하는 데 사용되는 컨트롤

슬라이더 생성의 3단계

  1. 슬라이더를 생성하고, 슬라이더가 나타내는 값의 범위를 지정
  2. 적절한 색상과 이미지를 이용해 슬라이더의 모양을 구성
  3. 하나 이상의 메서드를 슬라이더와 연결

사용자 상호작용에 반응하기
사용자가 슬라이더의 값을 변경하면 슬라이더에 연결된 메서드가 호출되어 원하는 작업이 실행
기본적으로는 사용자가 슬라이더의 Thumb를 이동시키면 연속적으로 이벤트를 호출하지만, isContinous 프로퍼티값을 false로 설정하면 슬라이더의 Thumb에서 손을 떼는 동시에 이벤트를 호출

슬라이더와 메서드 연결하는 방법

  • addTarget(_:action:for:) 메서드 사용
  • 인터페이스 빌더에서 연결 (@IBAction)

슬라이더와 연결하는 메서드 형식

슬라이더의 값을 변경했을 때 필요한 정보에 따라 아래 세 가지 중 한 가지를 선택하여 사용

func doSomething()
func doSomething(sender: UISlider)
func doSomething(sender: UISlider, forEvent event: UIEvent)

슬라이더 주요 프로퍼티

슬라이더의 프로퍼티 값을 설정하는 방식에는 프로그래밍 방식과, 스토리보드의 인스펙터를 이용한 방법이 있다.

  • var minimumValue: Float, var maximumValue: Float: 슬라이더 양끝단의 값
  • var value: Float: 슬라이더의 현재 값
  • var isContinuous: Bool: 슬라이더의 연속적인 값 변화에 따라 이벤트 역시 연속적으로 호출할 것인지의 여부
  • var minimumValueImage: UIImage?, var maximumValueImage: UIImage?: 슬라이더 양끝단의 이미지
  • var thumbTintColor: UIColor?: thumb의 틴트 색상
  • var minimumTrackTintColor: UIColor?, var maximumTrackTintColor: UIColor?: thumb를 기준으로 앞쪽 트랙과 뒤쪽 트랙의 틴트 색상

슬라이더 주요 메서드

//  슬라이더의 현재 값 설정
func setValue(Float, animated: Bool)

//  특정 상태의 minimumTrackImage 반환
func minimumTrackImage(for: UIControlState) -> UIImage?

// 특정 상태의 minimumTrackImage 설정
func setMinimumTrackImage(UIImage?, for: UIControlState)

// 특정 상태의 maximumTrackImage 반환
func maximumTrackImage(for: UIControlState) -> UIImage?

// 특정 상태의 minimumTrackImage 설정
func setMaximumTrackImage(UIImage?, for: UIControlState)

//  특정 상태의 thumbImage 반환
func thumbImage(for: UIControlState) -> UIImage?

//특정 상태의 thumbImage 설정
func setThumbImage(UIImage?, for: UIControlState)

swift 인터페이스 빌더와 객체를 코드와 연결(IBAction)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


인터페이스 빌더와 객체를 코드와 연결(IBAction)

인터페이스 빌더에서 생성된 객체에서 발생한 액션을 코드와 연결한다. > 사용자 동작에 상호 작용을 할 수 있도록 한다

즉, 실제 앱에서 터치를 통해 일어나는 반응을 확인하는 작업!

컨트롤 이벤트의 종류

컨트롤 이벤트는 UIControl에 Event라는 타입으로 정의되어 있다. 아래는 컨트롤 객체에 발생할 수 있는 이벤트의 종류!

touchDown

컨트롤을 터치했을 때 발생하는 이벤트 > UIControl.Event.touchDown

touchDownRepeat

컨트롤을 연속 터치 할 때 발생하는 이벤트 > UIControl.Event.touchDownRepeat

touchDragInside

컨트롤 범위 내에서 터치한 영역을 드래그 할 때 발생하는 이벤트 > UIControl.Event.touchDragInside

touchDragOutside

터치 영역이 컨트롤의 바깥쪽에서 드래그 할 때 발생하는 이벤트 > UIControl.Event.touchDragOutside

touchDragEnter

터치 영역이 컨트롤의 일정 영역 바깥쪽으로 나갔다가 다시 들어왔을 때 발생하는 이벤트 > UIControl.Event.touchDragEnter

touchDragExit

터치 영역이 컨트롤의 일정 영역 바깥쪽으로 나갔을 때 발생하는 이벤트 > UIControl.Event.touchDragExit

touchUpInside

컨트롤 영역 안쪽에서 터치 후 뗐을때 발생하는 이벤트 > UIControl.Event.touchUpInside

touchUpOutside

컨트롤 영역 안쪽에서 터치 후 컨트롤 밖에서 뗐을때 이벤트 > UIControl.Event.touchUpOutside

touchCancel

터치를 취소하는 이벤트 (touchUp 이벤트가 발생되지 않음) > UIControl.Event.touchCancel

valueChanged

터치를 드래그 및 다른 방법으로 조작하여 값이 변경되었을때 발생하는 이벤트 > UIControl.Event.valueChanged

primaryActionTriggered

버튼이 눌릴때 발생하는 이벤트 (iOS보다는 tvOS에서 사용) > UIControl.Event.primaryActionTriggered

editingDidBegin

UITextField에서 편집이 시작될 때 호출되는 이벤트 > UIControl.Event.editingDidBegin

editingChanged

UITextField에서 값이 바뀔 때마다 호출되는 이벤트 > UIControl.Event.editingChanged

editingDidEnd

UITextField에서 외부객체와의 상호작용으로 인해 편집이 종료되었을 때 발생하는 이벤트 > UIControl.Event.editingDidEnd

editingDidEndOnExit

UITextField의 편집상태에서 키보드의 return 키를 터치했을 때 발생하는 이벤트 > UIControl.Event.editingDidEndOnExit

allTouchEvents

모든 터치 이벤트 > UIControl.Event.allTouchEvents

allEditingEvents

UITextField에서 편집작업의 이벤트 > UIControl.Event.allEditingEvents

applicationReserved

각각의 애플리케이션에서 프로그래머가 임의로 지정할 수 있는 이벤트 값의 범위 > UIControl.Event.applicationReserved

systemReserved

프레임워크 내에서 사용하는 예약된 이벤트 값의 범위 > UIControl.Event.systemReserved

allEvents

시스템 이벤트를 포함한 모든 이벤트 > UIControl.Event.allEvents

swift 인터페이스 빌더와 객체를 코드와 연결(IBOulet)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


인터페이스 빌더와 객체를 코드와 연결(IBOulet)

생성된 인터페이스 빌더의 객체를 코드(프로퍼티)와 연결하는 작업을 해보자.

  1. 버튼을 control을 누른상태에서 원하는 곳에 드래그 > 객체 이름 설정
  2. view control을 누른 뒤 드래그

프로퍼티의 이름 변경

[Refactor] > [Rename]

이 방법으로 하지 않으면 자동으로 변경된 이름으로 객체를 연결해주지 않는다.

swift 기본문법 - 사용자정의 연산자(Custom Operators)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


사용자정의 연산자(Custom Operators)

Swift는 사용자가 원하는 동작을 하는 연산자를 생성할 수 있다. 그렇기에 Swift에서 연산자는 부호로 표현하는 함수라고 할 수있다.

연산자의 종류

Swift의 연산자는 총 3 종류로 전위, 중위, 후위로 구성

1.전위 연산자: 연산자가 피연산자 앞에 위치하는 연산자

// 대표적인 예) 논리 부정 연산자
a = !a

2.중위 연산자: 연산자가 두 피연산자 사이에 위치하는 연산자

// 대표적인 예) 기본적인 연산자들
a + b
a += b
a - b

3.후위 연산자: 연산자가 피연산자 뒤에 위치하는 연산자

// 대표적인 예) 옵셔널 관련 연산자
a?
a!

연산자는 /, =, -, +, _, %, <, >, &, |, ^, ?, ~ 를 결합하여 만들 수 있다.

마침표(.)을 이용하여 사용자를 만들수 있지만 연산자 문자 중 맨 처음 문자가 마침표여야 하며 .+.는 사용 가능하지만 +.+와 같이 선언하면 +와 .+연산자 로 나누어 인식하게 된다. 물음표와 느낌표는 연산자에 포함 가능하지만 자체적으로 재정의는 불가능하다.

토큰 =. ->, //, /_, */전위 연산자 <, &, ? 중위 연산자 ? 후위 연산자 >, !, ? 역시 재정의가 불가능

전위 연산자

전위 연산자를 구현하기 위해 prefix라는 키워드를 사용

// 연산자를 구현하기 위해 미리 선언
prefix operator **

// 제곱을 수행하는 연산자를 정의
prefix func ** (num: Int) -> Int{
    return num * num
}
print(**100)
// 10000

위의 연산자를 재정의 하지 않고 기능만 추가하려면 연산자를 선언하지 말고 함수를 overload

//논리 부정 연산자를 String에서도 사용 가능하도록 기능을 추가
prefix func ! (str: String) -> Bool{
    return str.isEmpty()
}
// !을 통해 String의 값이 비었는지 확인 가능
print(!"")
// true

후위 연산자

후위 연산자를 구현하기 위해 postfix라는 키워드를 사용

postfix operator ++
// 전위와 같이 연산자를 구현하기 위해 미리 선언

// 값에 1을 더하는 연산자를 만든다
postfix func ++ (num: Int) -> Int{
    return num + 1
}
print(1++)
// 2

하나의 피연산자에 전위와 후위를 한 줄에 사용하게 되면 후위가 먼저 실행

print(**10++)
// (11) * (11)
// 121

중위 연산자

중위 연산자의 종류는 다양하다. 그렇기에 중위 연산자는 특별히 우선순위를 가지는데, 중위 연산자의 우선순위는 더 높은 우선순위, 더 낮은 우선순위, 결합방향, 할당방향을 명시하며 중위 연산자에 우선순위를 명시하지 않으면 우선순위가 가장 높은 DefalutPrecedence그룹이 할당된다.

infix operator <=
// 연산자를 미리 선언

// 서로의 문자의 수를 비교하는 연산자
func <= (str1: String, str2: String) -> Bool{
    return str1.size <= str2.size
}
print( "hello" <= "nice" )
// false