TIL

16일차 TIL

h_luz 2024. 3. 19. 21:35
Swift 알고리즘 및 언어공부

 

//37. 행렬의 덧셈

func solution(_ arr1:[[Int]], _ arr2:[[Int]]) -> [[Int]] {
    var arrResult:[[Int]] = []
    for i in 0..<arr1.count {
        var arrSum = zip(arr1[i],arr2[i]).map(+)
        arrResult.append(arrSum)
    }
    return arrResult
}

으악.. 행렬이라니 너무 헷갈렸다..

안 그래도 배열은 내게 너무 복잡한 존재인데 ㅠ

이 문제를 보고 zip함수가 떠오르긴 했는데 어떻게 사용할지가 관건이었다.

그래도 풀어서 다행.. 풀고나니까 별거 없다.. ㅜ

 

전에 노션에서 zip함수 정리하기는 했지만, 한 번 더 살펴보기 !

 

zip 함수 (참조)

: 내장 함수, 두 개 이상의 시퀀스를 조합하여 하나의 새로운 시퀀스를 생성

let numbers = [1, 2, 3, 4, 5]
let numbers2 = [2, 3, 4, 6, 7]

let zipped = zip(numbers, numbers2)
print(zipped.map(*)) //[2, 6, 12, 24, 35]

이런 식으로 두 개의 배열을 조합해서 하나의 시퀀스를 만든 후에 map 함수로 다 곱할 수 있다.

배열뿐만 아니라 다른 종류의 시퀀스도 조합 가능

 

그리고 놀랍게도 더 짧은 코드가 있다. (사실 그럴 줄 알았다.. )

//다른 사람의 풀이
func solution(_ arr1:[[Int]], _ arr2:[[Int]]) -> [[Int]] {
    return zip(arr1, arr2).map{zip($0,$1).map{$0+$1}}
}

ㅠㅠ 아 ㅠㅠ 코드 줄이기 정말 너무 어렵다.. ㅠ

내가 for문으로 돌려준 것을 map 고차함수로 간단하게 표현했다.

난 사실 for문을 map 고차함수로 사용하는 게 제일 어렵다 . . . ㅠ 

 

//38. 직사각형 별 찍기
import Foundation

let n = readLine()!.components(separatedBy: [" "]).map { Int($0)! }
let (a, b) = (n[0], n[1])
for _ in 1...b {
    for _ in 1...a {
        print("*", terminator: "")
    }
    print("\n")
}

 

처음 시도는 이렇다 ! 결과적으로 이 코드는 잘 되지 않았다..ㅠ

command lind code에서 할 때는 잘 나왔는데 뭔가 스트링 하나에 모든 별을 담아서 출력해야 하는 것 같았다.

 

* 그리고 위에 두 줄 코드는 입력받은 값을 a와 b에 넣어주는 내용이다 

 

그리고 여기서 주의할 점을 살펴보자

1. readLine()은 String 타입을 리턴하고, 옵셔널 타입으로 리턴된다.

 

그리고 그 뒤에 나오는 함수 components 함수를 살펴보자면

 

Components()

: 특정 문자를 기준으로 문자열을 자를 때 사용하는 함수

  • import Foundation을 선언해 주어야 사용 가능
  • String을 리턴한다.
  • separatedBy: 에 문자열을 자르는 기준을 입력

예시

let str = "hello world, nice to meet you. :)"

var oneSeperator = str.components(separatedBy: " ")
//["hello", "world,", "nice", "to", "meet", "you.", ":)"]

var manySeperator = str.components(separatedBy: [",", "."])
// seperator 여러 개 사용 가능
// ["hello world", " nice to meet you", ":)"]

 

* split이라는 함수도 있다 ! https://nareunhagae.tistory.com/8

 

그리고 저 terminator에 대해서 알아보자면 https://applecider2020.tistory.com/6

print 함수의 정의를 보면 알 수 있다.

func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

정의를 보면 print를 하면 줄 바꿈이 자동으로 설정되어 있다.

그래서 terminator 없이 출력하면 기본 값으로 나오기 때문에 한 줄로 줄줄이 나온다..

그래서 terminator에 "" 이렇게 아무것도 넣지 않아서 별 문자들이 줄줄이 나올 수 있도록 설정한 것!

그리고 a개의 별문자가 입력한 수만큼 나오면 print("\n")으로 줄 바꿈을 넣어줬다. 

 

근데 이렇게 문제를 풀면 아마 a가 5고 b가 3이라는 가정하에

"*****"

"*****"

"*****"

이런 식으로 출력되지 않을까..?

근데 문제가 원하는 답은 

"*****

*****

*****"

이런 식인 것 같음 ㅎ

 

그래서 다시 풀어보았다.

import Foundation

let n = readLine()!.components(separatedBy: [" "]).map { Int($0)! }
let (a, b) = (n[0], n[1])

var sArr:[String] = []
for _ in 1...a {
    sArr.append("*")
}
for _ in 1...b {
    let result = sArr.joined()
    print(result)
}

 

이렇게 배열에 묶어줘서 출력하니까 정상적으로 나왔다 !

그럼 여기서는 joined()를 살펴보자.

 

Joined(separator:)

: 각 요소 사이에 지정된 구분 기호를 통해 시퀀스의 연결된 요소 반환

위에 별 코드를 보면 separator 없이 sArr를 연결해서 한 줄로 만들어주었다.

let nestedNumbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let joined = nestedNumbers.joined(separator: [-1, -2])
print(Array(joined))
// Prints "[1, 2, 3, -1, -2, 4, 5, 6, -1, -2, 7, 8, 9]"

연결되는 중간중간에 -1, -2를 볼 수 있다.

 

//다른 사람의 풀이

import Foundation

let n = readLine()!.components(separatedBy: [" "]).map { Int($0)! }
let (a, b) = (n[0], n[1])

for _ in 0..<b {
    print(Array(repeating: "*", count: a).joined())
}

이건 다른 사람의 풀이인데 repeating에 대해서 기억하기 위해서 가져옴 !

 

Init(repeating: count: )

: 지정된 수의 단일 반복 값을 포함하는 새 컬렉션을 만든다.

let fiveZs = Array(repeating: "Z", count: 5)
print(fiveZs)
// Prints "["Z", "Z", "Z", "Z", "Z"]"

repeating 값을 count 만큼 반복하는 함수 !

나중에 유용하게 쓰이지 않을까?

 

하 오늘 swift 알고리즘 뭔가.. 어렵고, 오래 걸렸다..

빨리 강의 들어야지 !

 


 

IOS 앱 개발 입문

 

UIScrollView : 화면에서 스크롤 가능한 영역을 제공한다.

 

스크롤뷰 생성

let scrollView = UIScrollView(frame: view.bounds)

 

https://babbab2.tistory.com/46 bounds에 대한 내용이 있는데 점.. 어렵다..

frame과 bounds에 차이? 에 대해서 설명이 잘 되어있음

결국 bounds는 스크롤 뷰를 사용하기 위해서 필요한 거 같음 !

링크에서 가져온 정보

 

스크롤뷰 크기

scrollView.contentSize = CGSize(width: view.frame.width, height: view.frame.height * 2)

여기에서 

width는 view.frame.width 즉, 뷰의 프레임과 같은 크기로 설정되어 있기 때문에 좌우로는 스크롤이 불가능하지만,

height에 *2 즉, 뷰 프레임 크기에 2배의 사이즈를 정해주었기 때문에 위아래 스크롤이 가능한 사이즈이다.

 

스크롤뷰 설정

scrollView.isScrollEnabled = true // 스크롤링 기능
scrollView.isPagingEnabled = false // 페이지 기능
scrollView.bounces = true

 

bounces

: 스크롤 뷰가 콘텐츠 가장자리를 지나 다시 튀어 오르는지 여부를 제어하는 ​​부울 값

이 속성의 값이 true이면 스크롤 뷰는 콘텐츠의 경계를 만나면 바운스 됩니다. bounces는 스크롤이 콘텐츠의 가장자리에 도달했음을 시각적으로 나타냅니다. 값이 false이면 튕김 없이 콘텐츠 경계에서 스크롤이 즉시 중지됩니다. 기본값은 true. 

 

Try

UIScrollView 실습

시뮬레이터를 잘 보면 옆에 스크롤 바? 가 있다.

bounces를 false로 하면 저 스크롤 바가 튕기지 않고, 정적인 움직임을 갖는다.

isPagingEnabled를 true로 하면 중간에서 멈출 수 없고, 페이지가 딱딱 나눠져 있음

isScrollEnabled를 false로 하면 저 스크롤바 자체가 나오지 않아서 스크롤이 불가능함 !

 


 

UIPickerView: 사용자가 여러 개의 옵션 중 하나를 선택할 수 있는 휠 형식의 UI 요소

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
   let pickerView = UIPickerView() //pickerView 생성
   let datas = ["Optino1", "Option2", "Option3"]

 

UIPickerViewDelegate, UIPickerViewDataSource 프로토콜을 채택해야지 사용할 수 있다.

 

 

pickerView.delegate = self
pickerView.dataSource = self
pickerView.center = view.center
view.addSubview(pickerView)

delegate와 dataSource를 self로 지정해 줘서, 해당 데이터나 이벤트를 처리하는 객체를 상위에 ViewController로 지정한다고 명시

(솔직히 잘 이해가 안 가지만.. 사용하다 보면 이해되지 않을까 . . . ? )

 

func numberOfComponents(in pickerView: UIPickerView) -> Int {
	return 1 //dataSource에 필수 , 컴포넌츠의 수
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
	return datas.count //총 데이터 수
}
//여기서 components는 0부터 시작

UIPickerViewDataSource 메소드  -> numberOfComponents : 섹션의 개념과 유사

pickerView는 여러 구성요소를 가질 수 있기 때문에

데이터를 몇 행을 지정할지 데이터의 개수를 메소드로 설정한다.

 

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> STring? {
	return data[row] //각 타이틀을 붙이기 위해 담긴 String 값을 이용
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
	print("Selected: \(data[row])") // didSelectRow를 통해 선택되었을 때 print 될 내용
}

UIPickerViewDelegate           * Delegate는 위임해서 어떠한 이벤트를 처리한다.

-> 실제 이벤트를 설정할 수 있다.

 

Try

UIPickerView 실습

pickerView 뭔가 써먹을 때가 많을 것 같다 ! 기억해 둬야지 

 


 

드디어 내가 가장 어려워하는 UITableView..

이건 예전에 UI 강의 들으면서도 어려워서 계속 공부해야지 하면서 못했던 부분인데ㅜ

이번 과제할 때도 중요하다고 하고,, 그래서 열심히 공부해야겠다고 생각함..

 

그때 UITableView 공부하면서 유용할 것 같아서 찾아놓은 링크

 

UITableView : 데이터 목록 표시, 사용자와 상호작용할 수 있는 스크롤 가능한 UI 요소

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
	let tableView = UITableView() //tableView 생성
    let datas = ["Optino1", "Option2", "Option3"]

pickerView와 마찬가지로 사용하기 위해서 데이터와 이벤트를 처리해 줄 프로토콜들이 필요한데

그래서 시작 전에 UITableViewDataSource와 UITableViewDelegate 프로토콜을 ViewController에서 채택

 

override func viewDidLoad() {
	super.viewDidLoad() //view가 load되는 위치.
    
  	tableView.frame = view.bounds
  	tableView.dataSource = self
   	tableView.delegate = self
   	tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    //셀 값 가져오기
   	view.addSubview(tableView)
}

view가 로드된 시점에서 dataSource와 delegate를 self로 설정해서 해당 데이터와 이벤트를 자기 자신인 ViewController로 지정

 

UITableViewDataSource 필수 설정 요소들

//테이블의 행 수
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
	return datas.count //row가 몇 개인지
}
//테이블의 각 행에 대한 셀
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
	let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = datas[indexPath.row]
    return cell //행에 들어갈 셀의 내용과 같은 것들을 제공
}
  1. 테이블의 행 수 ( section이 행 수를 결정 )
  2. 테이블의 각 행에 따른 셀 (아마 테이블뷰 셀에 내용들을 넣는 것 같음. 따로 파일로 만들어서 사용하기도 함)

UITableViewDelegate : 이벤트 구현 가능

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
	print("Selected: \(datas[indexPath.row])")
    tableView.deselectRow(at: indexPath, animated: true)
    //행을 탭 했을 때 음영이 생기지만 탭 했다가 뗐을 때 음영을 해제하는 deselectRow 속성
    //false로 설정하면 탭을 떼도 계속 음영을 갖고있다.
}

 

Try

UITableView 실습

 

확실히 전에 들었던 것보다는 이해가 가는 것 같지만, 과제를 해봐야 제대로 사용할 수 있는 건지 뭔 지 알 것 같다 . . .

화이팅 !


 

UICollectionView : 그리드 레이아웃으로 아이템 목록을 표시하고, 사용자와 상호 작용할 수 있는 스크롤이 가능한 UI 요소

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegatedFlowLayout {
	let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
    let datas = ["Option1","Option2","Option3"]

마찬가지로 UICollectionViewDataSource와 UICollectionViewDelegate 프로토콜을 채택해 주는데, 이번엔 UICollectionViewDelegateFlowLayout 도 채택함.

 

? 근데 여기서 collectionView 생성할 때 frame에 .zero는 무슨 뜻일까나..

 

collectionView.frame = view.bounds
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = .white

self.view.addSubview(collectionView)

테이블뷰와 유사하다. 여튼 이렇게 collectionView 설정.

 

UICollectionViewDataSource 필수 요소

//행 수
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
	return datas.count
}

//행에 대한 셀
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
	let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for:indexPath)
    cell.backgroundColor = .lightGrey
    return cell
}

1. 행 수

2. 행에 대한 셀

 

테이블 뷰와 같다.

 

UICollectionViewDelegate

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
	print("Selected: \(datas[indexPath.row])")
    collectionView.deselectItem(at: indexPath, animated: true)
}

행이 선택되었을 때 이벤트

 

UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {  
        return CGSize(width: 100, height: 100)  
}

이 프로토콜 채택 시 사용할 수 있는 메소드는 셀의 크기를 지정할 수 있음!

 

Try

UICollectionView 실습

나중에 여러 option들을 넣어서 스크롤할 수 있게 만들 수 있지 않을까 하는 생각.. ?

테이블 뷰랑 비슷한 원리인 것 같다.

 


 

아.. 화면 그리기 강의를 다 못 끝내다니...!!!

오늘은 뭔가 집중이 잘 안 되는 날이었다.. 게다가 알고리즘 풀기에서 너무 시간을 많이 써버려서.. ㅠ

내일은 정말 강의를 끝내고 counter 예제를 만들어야겠다..

과제는 목요일부터... 🫠

 

UITableView나 UIPickerView 같은 거는 전에 해봤을 때보다 쉽게 느껴져서 다행이다..

뭔가 하나하나 뜯어서 공부하면 좀 알 것 같기도..? 하지만 그래도 아직 어렵고,, 멀고도 험한 코딩의 길..

많은 실습과 도전이 필요해 보인다.. 그래도 나중에 진짜 앱 만들 때 적용해 볼 생각 하면 그나마 힘이 난다.. !

화이팅..

'TIL' 카테고리의 다른 글

20일차 TIL  (3) 2024.03.25
19일차 TIL  (3) 2024.03.22
18일차 TIL  (2) 2024.03.21
17일차 TIL  (1) 2024.03.20
15일차 TIL  (4) 2024.03.18