하지마이씌

https://simth999wrld.tistory.com/82

위 게시물 이후 3개월 후 군여 훠훠 ㅋ

저는 잘 살아있습니다 아니 죽어있나..? 아무튼 새해 복 다들 많이 받으시길 바랍니다! 누가읽을진 모르겠지만..(매크로 쳐내)

개발을 공부하고 있냐구 말하신다면... 그럼요 요즘 잘 진행하고 있는 것 같습니 다? 

iOS에 대해 조금씩 공부하면서 요즘은 플러터도 조금씩 맛보는 중입니다요~ 예제코드 돌려보면서 이런저런 앱들 만들어 보는즁..

 

이번년도엔 취직을 할 수 있을까여? 

     ㄴ 몰루?

     ㄴ ㅋㅋ 빨리하셈;;

     ㄴ (작성자) 아 가능;;!!

 

제가 조그만한 개인 프로젝트를 진행중입니다. 메트로놈 앱입니다. 제가 밴드를 하고있어서 메트로놈을 사용하는데 조금씩 불편한곳이 있더라구요?? 제 입맛에 따라 만들어 보고 싶어서 만들고있습니다.

여기서 모두 같은 bpm을 동시간대에 같이 보는 기능이 있어숴!! Swift로 서버를 만들 수 있는 Vapor로 프로젝트를 진행하는 중입니다요.

이 이야기는 vapor에대한 내용..

 

배운점

Vapor?

vapor는 Swift로 작성된 서버 사이드 웹 프레임워크로 백엔드, 웹 앱 Api 및 HTTP 서버를 구출할 수 있게 됩니다!

 

설치방법

https://docs.vapor.codes/ko/install/macos/

설치방법은 위 링크 참조 해서 따라하셔용~

 

프로젝트 생성

vapor가 성공적으로 설치가 되었다면 밑의 명령으로 새로운 프로젝트를 생성할 수 있습니다~

vapor new 프로젝트이름 -n

 

이후 프로젝트 이름으로된 폴더에 이동해

swift run

의 명령어로 vapor를 실행할 수 있습니다.

 

폴더구조

├── Public
├── Sources
│ ├── App
│ │ ├── Controllers
│ │ ├── Migrations
│ │ ├── Models
│ │ ├── configure.swift
│ │ ├── entrypoint.swift
│ │ └── routes.swift
├── Tests
│ └── AppTests
└── Package.swift

 

크아악 폴더구조는 링크 에 들어가면 아주 친절하게 정리가 되어있지만! 저도 공부를 해야하니 조금 끄적여 보겠습니다.

 

Public

정적 파일을 저장하는 폴더.

일반적으로 이미지, 스타일시트, 브라우저 스크립트 등이 포함됩니다.

FileMiddleware가 활성화 되면 자동으로 서빙됨.

Tests

XCTest 기반의 단위 테스트 코드가 위치하는 폴더

Sources

프로젝트의 모든 Swift 소스파일이 들어있음.

최상위 폴더인 App은 SPM manifest에 선언된 대로 모듈을 반영함

Sources/App

모든 애플리케이션의 로직이 있는곳

Sources/App/Controller

애플리케이션의 로직을 그룹화 할수 있는 곳.

대부분의 컨드롤러는 요청을 수락하고 응답을 반환하는 많은 함수가 있음.

Sources/App/DTOs

링크

DTOs는 Data Transper Objects라는 뜻

데이터 전송 및 변환을 명확하고 안전하게 관리하기 위해 있다고해.

DTO는 클라이언트와 서버 간 데이터를 주고받을 때 사용되는 객체를 말해

Sources/App/Migrations

Fluent 데이터 베이스 마이그레이션 파일들이 위치

데이터베이스 스키마 변경사항을 관리

테이블 생성, 수정등의 마이그레이션 정의

Sources/App/Models

데이터 구조를 정의하는 파일이 위치.

Content 프로토콜을 준수하는 구조체가 위치함

Content 프로토콜
-> Json 자동 변환 지원
-> 요청, 응답 핸들링 간소화 : 클라이언트가 보낸 JSON 데이터를 구조체로 쉽게 받을 수 있음.
-> 다양한 데이터 포멧 지원
-> validatable를 사용하여 데이터의 유효성을 검증할 수 있음.

따라서
Vapor에서 데이터 모델을 HTTP 요청/응답 처리에 쉽게 사용할 수 있도록 해주는 핵심 기능입니다. 이를 통해 데이터 변환, 유효성 검증, 다양한 포맷 지원 등 많은 작업이 간소화되고, 코드의 유지보수성이 높아집니다.

 

Sources/App/configure.swift

이파일엔 configure(_:) 함수가 포함되어 있음.

앱의 설정을 담당

앱 구동에 필요한 초기 설정을 수행

데이터베이스, 미들웨어, 라우터등 서비스 등록

Sources/App/entrypoint.swift

@main 이 있는 파일

앱을 설정하고 실행하는 역할

configure.swift를 호출하여 앱을 구성

Sources/App/routes.swift

API 엔드포인트를 정의하는 파일

모든 라우트 설정이 이루어지는곳

HTTP 요청에 대한 핸들러를 정의

 

생각과 감정

간단하게 vapor를 알아보았습니다~ 물론 다만들어진건 아니구요 아직 조금씩 공부하면서 만드는중입니더~

아 그냥 파이어베이스나 슈퍼베이스 쓸걸 ㅋㅋ

 

https://github.com/jjwon2149/Metronome/tree/main/Server/MetronomeServer

 

Metronome/Server/MetronomeServer at main · jjwon2149/Metronome

합주를 위한 앱. Contribute to jjwon2149/Metronome development by creating an account on GitHub.

github.com

https://docs.vapor.codes/

 

Vapor Docs

Welcome Welcome to the Vapor Documentation! Vapor is a web framework for Swift, allowing you to write backends, web apps APIs and HTTP servers in Swift. Vapor is written in Swift, which is a modern, powerful and safe language providing a number of benefits

docs.vapor.codes

https://www.postgresql.org/

 

PostgreSQL

The world's most advanced open source database.

www.postgresql.org

 

 

 

ToDo
✅ udemy swiftUI강의
✅ 운동
✅ 나태한 나를 반성하기.

 

흠 오늘은 어제 유데미 강의를 보며 클론한 코드를 다시 하나씩 뜯어보며 

사용된 내용들을 잘근잘근 씹어서 삼켜보도록 하겠습니다..

 

배운점

Hacker News를 볼수있는 간단한 앱을 클론 했습니다만,,~~

networking, URLSession, Json decode등을 알수 있었쥐만,,,~~

네트워킹 부분에서 https://news.ycombinator.com/ 의 제목, id 등등을 가져와야 했습니다.

이 과정에서 항상 썼던 

class NetworkManager: ObservableObject {
    
    @Published var posts = [Post]()
    
    func fetchData() {
        if let url = URL(string: "https://hn.algolia.com/api/v1/search?tags=front_page") {
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { data, response, error in
                if error == nil {
                    let decoder = JSONDecoder()
                    if let safeData = data {
                        do {
                            let results = try decoder.decode(Results.self, from: safeData)
                            DispatchQueue.main.async {
                                self.posts = results.hits
                            }
                        } catch {
                            print(error)
                        }
                    }
                }
            }
            task.resume()
        }
    }
}

 

위의 fetchData()의 함수부분을 생각없이 코드를 집어넣었지만 한줄 한줄 뜯어 보다보니, 잊고있었던

async await의 개념을 공부하게 되었습니다.

 

async await을 공부하기 위해 이 블로그를 보며 공부를 하는 중이었지만,, 처음 보는 부분이라 이해가 잘 되지 않더라구요..
그래서! 기억난 async swift에서 발표하신 내용을 확인후 다시 블로그를 보며 공부 했습니다...
(진짜 이 발표 이해 굳굳으로 됨... 발표도 그렇고 블로거 수진님...정말 캄사함다.. 저도 블로그 짜집기 하며 정리를 해보겠슴다..) 

 

DispatchQueue.main.async

 

Swift의 코드는 한줄의 코드가 문장처럼 읽히게 작성 한다라고 어디서 주워 들었던것 같네요..ㅎㅎ
(궁금하면 다시 코드 컨벤션을 찾압 보겠습니다.)

 

하튼 DispatchQueue 큐로 보낸다는 뜻인것 같군요.

main 메인 으로 보낸다는것 같군요.

async 방식으로 한다는것 아닐까요?

메인 디스패치큐에 비동기로 task를 보낸다는것 같군요!!

 

네... ~~인것 같아요 ㅋㅋ

 

이글은 누구에게 async await을 알려주는 글이 아닌 오로지 저의 이해를 위한 글이니 다른

사람에 편의는 봐주지 않겠습니다..(하하..봐줘,,)

 

 

비동기(async)

메인 스레드가 자기한태 쌓여있는 다음 일을 실행한다.. 다음 라인을 실행한다 라구요..

queue에 보낸 작업은 생각하지 않고 바로 그 다음일을 한다 입니다..

 

동기(sync)

queue에 보낸 작업이 완료 될 때까지 기다린 후 다음 줄로 넘어갑니다.

 

queue.async { task } 또는 queue.sync { task }로 task를 queue로 보냈습니다.

queue에 쌓여있는 task들을 다른 스레드에 넣어 일을 해야겠습니다.

 

------------------------------------------------------------------------------

여기서 두개의 큐의 방식이 나오게 됩니다.

 

Serial(직렬)

serial queue는 한대의 스레드에서 처리하는 큐 입니다.

(여러개의 스레드가 있어도 한개의 스레드만 사용을 하는것 입니다.)

 

Concurrent(동시)

concurrent queue는 여러개의 스레드에서 처리하는 큐 입니다.

 

두개의 큐 방식중 어떤것을 사용해야 하는가??( 난 몰루? 항상 빠른것이 짱임 ㅋㅋ)

순서가 중요한 작업이면 serial queue, 순서가 중요하지 않고 빨리 끝내야 하는 작업이면 concurrent queue방식을 

사용 해야 한다고 하네요 껄껄

 

async sync, serial concurrent를 두개씩 묶어 생각하지 않고 별도의 개념으로 받아드려요,,,

 

async, sync -> 작업을 보내는 시점에서 기다릴지 말지에 대해 다루는것

 

serial, concurrent -> 큐에 보내진 작업을 여러개의 스레드에 보낼지 한개의 스레드로 보낼지에 대해 다루는 것

 

 

 

Dispatch Queue의 종류

 

1. main Queue

: 오직 한개만 존재하는 큐, Serial의 특성을 가짐, 이곳에 할당된 task는 메인 스레드에서 처리(UI 업데이트 내용 처리)

 

2. global Queue

: concurrent의 특성을 가진 큐, QoS(qualith of service)에 따라 여러개의 종류로 나뉨.

 

QoS(qualith of service) 6종에 대해 또한 알아야 겠습니다.

 

- userInteractive

사용자와 직접 상호작용 하는 작업 ( UI업데이트, 애니메이션 등)

메인스레드에서 처리하면 많은 로드가 걸리는 작업을 userInteractive에서 처리하여

바로 동작하는 것처럼 보이게함.

 

- userInitiated

클릭과 같은 즉각적인 결과가 필요한 작업(저장된 문서열기 등..)

userInteractive보다는 조금 오래걸리고 유저가 어느정도 인지하고 있음

 

- default

일반적인 작업

 

- utility

progress bar와 함께 길게 싱행되는 작업 (데이터 다운로드 등,,,)

 

- background

유저가 인지하지 않는 시간이 덜 중요한 작업(동기화 및 백업 등,,,)

 

- unspecified 

Qos 정보가 없음 을 나타냄. (거의 사용할일 없다십니다 하하)

 

 

3. custom Queue

: 커스텀으로 생성, 디폴트로 Serial의 특서을 가진 큐 but Concurrent로 설정이 가능하다.

 

앞으로의 계획선언

요즘 공부에대한 목적을 잃고 다시 나태지옥에 빠지는 듯한 기분이 듭니다.. 

그래서 ios공부와 같이 플러터또한 시작해볼까 합니다.. 핳하...

뭐라도 하면서 흥미를 붙여야 좋지 않을까 합니다 하하..

'TIL' 카테고리의 다른 글

TIL_20240110 Swift_AppSandbox, NSCoder  (0) 2024.01.10
TIL_20240109 Swift_SingletonPattern  (0) 2024.01.09
TIL_20231226  (0) 2023.12.26
TIL_20231223  (0) 2023.12.23
TIL_20231221  (0) 2023.12.21

 

 

ToDo
✅ 운동은 못함 ㅋ (헬스장 쉼)
✅ 함께자라기 정독

 

 

어제는 과 선배와 동기와 함께 술자리를 가졌슴당 ㅎㅎ

문래는 공장단지 맞는거죠,,? 내부는 상당히 힙하고.. 크리스마스 기분이 물씬 ㅎㅎ

 

신나게 놀고 오늘은 "함께 자라기"를 읽었슴당 ㅎㅎ (카페왔는데 노트북 충전기를 안가져왔다 ㅋ)

 

그리고 토이프로젝트를 깃에 업로드 하였습니다 ^_^

https://github.com/jjwon2149/TodoApp

 

 

 

배운점

 

🐣🐥🐓 자라기

애자일에서 학습은 소프트웨어 개발에 큰 병목 중 하나이다. 그 이유는 일반 프로젝트에서 피드백의 주기가 느려서 결정을 내리고 학습을 한 후 다시 피드백을 받응ㄹ 시기에 이전에 내린 결정에 대한 이유를 기억하기 어렵다.

하지만 애자일 프로젝트에서는 당장 한 행동에 대한 피드백을 10분, 한시간, 하루 주기로 빠르고 지속적으로 받아 다음 주기에 교정할 수 있다.

피드백을 짧은 주기로 얻는 것, 실수를 교정할 기회가 있는 것이 학습에 중요한 요소이다.

실력이 좋은 사람은 당시에 어떤 결정을 어떠한 이유로 내렸는지 자세히 기록하고 나중에 다시 확인하여 피드백을 반드시 얻는다.

 

  1. 자신이 이미 가지고 있는 것들을 잘 활용하라
    • 새로운 것을 유입하기보다 이미 가지고 있는 것을 연결하여 시너지 효과가 나게 한다.
    • 새로운 것은 이미 가지고 있는 것과 연결하도록 해라
  2. 외부 물질을 체화하라
    • 하지만 내부 순환만 하면 수렴할 위험이 있기 때문에 외부 자극을 받으면 좋다.
    • 하지만 외부 자극을 빨리 자기화 해야 한다.
  3. 자신을 개선하는 프로세스에 대해 생각해 보라
    • A를 돌아보는 회고/반성 활동을 주기적으로 해라.
    • 나를 개선하는 과정을 어떻게 개선할지 고민해라.
  4. 피드백을 자주 받아라
    • 사이클 주기를 짧게 두어서 작은 실험을 해 순환율을 높여라.
    • 일찍, 자주 실패해라. 실패에서 학습하라
  5. 자신의 능력을 높여주는 도구와 환경을 점진적으로 만들어라.
    • 완벽한 환경에서 시작하기 보다 점진적으로 자신의 환경을 개선시켜라.
    • 완벽한 환경은 어느날 갖추어지기는 어렵다.

 

생각과 감정

함께자라기는 저를 되돌아볼수 있는 시간을 주는것 같습니다 ^_^ 한번 정독한 후 두번째 정독이라 조금더 이해가 빠르고 와닿습니담ㅁ..다디...

 

저번주 평일에 머리를 싸맨 TodoApp 그냥 기본 라이브러리 사용하면 되는걸 구지비 커스텀을 해서 ㅎㅎ,,, 그래도 유튜버가 친절하게 알려주더군요 ㅎㅎ 다음에 또 할 진 모르겠지만 좋은 경험이였습니다...

 

앞으로의 계획선언

"꾸준히 자기계발에 시간을 쏟으면 그것이 1년, 2년 뒤에 성장해서 돌아온다. 지식이나 능력은 복리로 이자가 붙는다." 

꾸준히 자기계발에 시간을 쏟아 보겠슴담,,,,다,,,디...

 

'TIL' 카테고리의 다른 글

TIL_20231221  (0) 2023.12.21
TIL_20231212  (0) 2023.12.12
TIL_20231120  (0) 2023.11.20
TIL_20231114  (0) 2023.11.15
TIL_20231113  (0) 2023.11.13

ToDo
✅ 간단한 Toy App만들기
✅ 운동 ㅋ
✅ 자존감지키기 ㅋㅋ

 

벌써 11월도 별로 안남았군요... 이제 남은건 크리스마스인가요~~ ㅋㅌㅋ

 

일찍 일어난겸 오전 운동을 다녀와서 의자에 앉아있습니다.

배운점

오늘은 iOS Academy에 있는 간단한 앱을 제작했습니다~

 

코드를 둘러보던중 익숙하지 않은 친구가 있더군요 ^^

 

바로 UserDefaults입니다.

 

UserDefaults
An interface to the user’s defaults database, where you store key-value pairs persistently across launches of your app.

 

Key-Value를 저장하는 기본 데이터베이스에 대한 인터페이스 라고 하군요

 

값 저장하기

UserDefaults.standard.set("Hello", forKey: "greet")

set(_:forKey:) 메서드를 사용하여 "Hello"란 문자열을 "greet"라는 키로 UserDefaults에 저장합니다.

 

값 가져오기

if let greet = UserDefaults.standard.string(forKey: "greet") {
    print(greet)
}
//Hello

string(forKey:) 메서드를 사용하여 "greet"에 저장되어있는 "Hello"문자열을 가져와 출력합니다.

 

값 제거하기

UserDefaults.standard.removeObject(forKey: "greet")

removeObject(forKey:) 메서드를 사용하여 "greet"에 해당하는 값을 제거합니다.

 

데이터 타입별 저장

// 숫자 저장
UserDefaults.standard.set(123, forKey: "onetwothree")

// 부울 저장
UserDefaults.standard.set(true, forKey: "isEmpty")

// 배열 저장
let fruits = ["Apple", "Banana", "Orange"]
UserDefaults.standard.set(fruits, forKey: "fruits")

 

UserDefaults는 작은 규모의 데이터를 다룰경우 사용된다고 합니다. 큰 규모의 데이터를 다룰 경우 외부 라이브러리나 CoreData를 사용 해야겠죠..? 그럼 CoreData도 알아야겠죠...?

'TIL' 카테고리의 다른 글

TIL_20231212  (0) 2023.12.12
TIL_20231126  (0) 2023.11.26
TIL_20231114  (0) 2023.11.15
TIL_20231113  (0) 2023.11.13
TIL_20231107  (0) 2023.11.07

ToDo
✅ Udemy 컴공선배 강의
✅ 운동

✅ Swift DelegatePattern

 

이번주만 탈락의 고배를 여러번 느꼈는데요,,하하 그러던중 오늘 한 영상을 보았습니다.

침착맨의 "대충 동기 부여하는 영상" 인데요, 조금 울적하던중 위로를 받았습니다 ^_^

궤도님이 한 말이 가장 마음에 남습니다.

"50%확률일때 하지않으면 다음 성공확률도 50%이다. 무조건 시도를 해봐야 다음 성공 확률이 올라간다는 의미입니다."

 

계속 도전하면서 다음 성공 확률을 조금씩 늘려가겠습니다 ^_^

 

나를 위로해준 최고 침착맨 고마워🙏

배운점

오늘은 간단히 회원가입을 할때 유효성 검사를 하기 위한 정규표현식을 같이 알아보았습니다.

    func isValidPassword() -> Bool {
        //비밀번호는 대,소문자,특수문자,숫자 and 8자이상
        let regularExpression = "^(?=.*[A-Z])(?=.*[a-z])(?=.*[\\d])(?=.*[~!@#\\$%\\^&\\*])[\\w~!@#\\$%\\^&\\*]{8,}$"
        let passwordValidation = NSPredicate.init(format: "SELF MATCHES %@", regularExpression)
        
        return passwordValidation.evaluate(with: self)
    }
    
    
    func isValidEmail() -> Bool {
        // @ 2글자
        let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        let emailTest = NSPredicate.init(format: "SELF MATCHES %@", emailRegEx)
        
        return emailTest.evaluate(with: self)
    }

 

 

자주 쓰는 정규식

대문자만

"^[A-Z]*$"

 

소문자만

"^[a-z]*$"

 

숫자만

"^[0-9]*$"
"^[\\d]*$"

// 반대 (숫자 제외)
"^[\\D]*$"

 

알파벳 + 숫자

"^[0-9a-zA-Z]*$"
"^[\\w]*$"

// 반대 (알파벳, 숫자 제외)
"^[\\W]*$"

 

숫자, 알파벳, 특수문자 (~!@#$%^&*)

"^[0-9a-zA-Z~!@#\\$%\\^&\\*]*$"
"^[\\w~!@#\\$%\\^&\\*]*$"

 

최소 하나 이상 something

"(?=.*[something])"

 

최소 하나 이상의 대문자, 하나 이상의 소문자, 하나 이상의 숫자

"(?=.*[A-Z])(?=.*[a-z])(?=.*[\\d])"

 

최소 하나 이상의 대문자, 하나 이상의 소문자, 하나 이상의 숫자, 하나 이상의 특수문자(~!@#$%^&*), 그 외 불포함

"^(?=.*[A-Z])(?=.*[a-z])(?=.*[\\d])(?=.*[~!@#\\$%\\^&\\*])[\\w~!@#\\$%\\^&\\*]{8,}$"

 

생각과 감정

위로해준 침착맨에게 감사해🙏

 

앞으로의 계획선언

인스타그램 클론한후 기능 붙이기에 돌입해보겠습니다 ^_^ 빻쉬

 

'TIL' 카테고리의 다른 글

TIL_20231126  (0) 2023.11.26
TIL_20231120  (0) 2023.11.20
TIL_20231113  (0) 2023.11.13
TIL_20231107  (0) 2023.11.07
TIL_20231006  (0) 2023.10.06

사람이 나태해지면 안됩니다... 여러분... 

어제밤인지 엊그제 밤인지 자기전에 문득 의심이 들었네요. 내가 가는 이 이 어디로 가는지~ 어디로 날 데려가는지~ ㅋㅋ

잠깐 의심했습니다. 하하 자기전에 생각이 많아지는건 저뿐인가요~? 

요즘 OPIC을 공부하는중인데 쉬운거 하나없죠~~ 유튜브에선 "선생님 강의 듣고 첫 시험부터 IL 받았어요~~" 라는 글밖에 보이지 않더라군요 하하

매년 영어를 접하였지만 실상 할지는 못하는 이 현실 ㅋ 입으로 뱉어보려 하면 밈 잔치가 일어납니다.. (다 힙플밈 때문이야 ㅈㅅㅋ)

여튼 이런 저런 생각을 접어두고 하던거를 계속 하려 합니다~

어제는 강의를 들어서 TIL을 못적었네요 (핑계) 

네 강의에서 MVC패턴에 대해서 공부를 하였는데 인터넷엔 없는것이 없죠?? 아주 정리를 잘한 여러 블로그에서 공부를 하였습니다.

 

배운점

디자인 패턴?

디자인 패턴은 보편적인 문제에 대한 증명된 해결책일 뿐입니다.

 

Xcode를 처음 접했을땐 ViewController에 모든 코드가 채워져 있습니다.

하지만 다른 View들이 만들어진다면 더욱 힘들어 지기 마련입니다.

 

MVC?

MVC 는 Model View Controller 의 약자 입니다.

 

Model : 어플리케이션이 "무엇"을 할것인지 정의합니다. 내부 비즈니스 로직을 처리하기 위한 역할을 할 것 입니다, 

앱에 포함 되어야 하는 데이터를 정의합니다.

 

View : 화면에 "무엇"을 "보여주기 위한 역할"을 합니다. 컨트롤러의 하위에 종속되어, 모델이나 컨트롤러가 보여주려 하는 모든 필요한 것을 보여줄 것입니다. 또한 사용자가 보는 화면이죠.

앱의 데이터가 표시되는 방법을 정의합니다.

 

Controller : Model과 View가 각각 무엇을 해야 할 지 알고 있고, 통제합니다. 비즈니스 로직을 처리하는 Model과 완전히 UI에 의존적인 View가 서로 직접 이야기 할 수 없게 합니다.

앱 사용자의 입력에 응답하여 모델, 뷰를 업데이트 하는 로직이 포함되어 있습니다.

출처 : https://developer.mozilla.org/en-US/docs/Glossary/MVC

 

생각과 감정

아직 비기너라 처음부터 나누어서 코드를 작성하는 것에 대해 감은 가져지지 않습니다.. 하지만 채용공고에서 늘상 보는 MVC, MVVM 패턴 항상 나오죠! 저도 찬찬히 알아가야 합니다!!

 

앞으로의 계획선언

다은은 MVVM패턴에 대해 알아 볼 것 입니다!

 

'TIL' 카테고리의 다른 글

TIL_20231107  (0) 2023.11.07
TIL_20231006  (0) 2023.10.06
TIL_20230918  (0) 2023.09.18
TIL_20230914  (0) 2023.09.14
TIL_20230913  (0) 2023.09.13

안녕하십니까..ㅎㅎ 당차게 애플아카데미를 2번 지원했었지만 인터뷰를 해보지도 못하고 떨어졌군요~~
어제는 조금 매음이 아프고 세상이 미웠지만 다시일어났습니다 하하~~

뭐 어쩌겠습니까 다른걸 또 도전하면 되지않겠나요!! 그래서 11월달에 메쉬업에 지원을 하려 합니다~!

그전에 저의 내실을 많이 쌓아 둬야겠죠? 다른 분들에게 많은 도움이 되어야죠 ㅎㅎ (실상 도움을 많이 받는편)
어제 다하지 못한 후행클로저를 공부한후 "객체지향의 사실과 오해"를 조금 읽어보려 합니다~ 화이팅!!

 

배운점

후행클로저에 대해 알아보았습니다.

 

후행클로저

함수의 마지막 인수로 함수에 클로저 표현식을 전달해야하고 클로저 표현식이 긴 경우 후행 클로저를 사용한다고 합니다!

예제를 보면서 알아보았습니다.

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:

someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

위의 코드에서 someFunctionThatTakesAClosure 함수는 하나의 매개변수를 가지고 있습니다.

이 매개변수는 closure라는 이름의 클로저입니다.

someFunctionThatTakesAClosure함수를 호출할 때 closure 매개변수에 클로저를 전달합니다. 클로저는 중괄호로 묶여 있습니다.

 

someFunctionThatTakesAClosure함수를 호출할 때 후행 클로저를 사용합니다! 

후행클로저는 함수의 마지막 매개변수로 전달되기 때문에 매개변수 이름을 생략할 수 있습니다.

 

마지막 someFunctionThatTakesAClosure()의 부분을 보시면 코드를 더욱 간결하게 사용할 수 있습니다.

특히 함수의 마지막 매개변수가 클로저인 경우 후행클로저를 사용하면 코드가 더욱 깔끔해집니다!!

주의할 점은 후행 클로저는 함수의 마지막 매개변수로만 사용할 수 있다는 점입니다!

 

reversedNames = names.sorted() { $0 > $1 }

문자열 정렬 클로저는 메서드의 소괄호 밖에 작성될 수 있습니다!

 

reversedNames = names.sorted { $0 > $1 }

후행 클로저로 표현식이 함수와 메서드의 유일한 인수일 경우 함수를 호출할때 ()를 생략해도 좋습니다!

 

후행 클로저는 클로저가 길어서 한줄로 인라인으로 작성이 불가능 할 때 유용합니다.

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

위의 예제는 0은 "Zero"등으로 숫자를 그에 해당하는 영어로 매핑하는 딕셔너리 입니다!

numbers 배열을 사용하여 후행 클로저로 map(_:)메서드로 클로저 표현식을 작성하여 String값의 배열을 생성 할 수 있습니다.

let strings = numbers.map { (number) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}
// strings is inferred to be of type [String]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]

클로저 몸체를 보시면,

number를 number로 초기화 하고있습니다.

output 변수를 ""로 초기화 하고있습니다.

repeat으로 number가 0이 될때까지 반복합니다.

반복문의 각 반복에서 클로저는 number의 나머지를 구하고, 해당하는 영어 이름을 output변수에 추가합니다. 

마지막으로 클로저는 output 변수의 값을 반환합니다.

따라서 map함수는 numbers 배열의 각 요소에 대해 위의 클로저를 실행하고, 각 요소에 대한 클로저의 결과를 배열 strings에 저장합니다.

( 딕셔너리의 서브 스크립트는 키가 존제하지 않는 경우에 값을 찾는걸을 실패하기 위해 옵셔널 값을 반환합니다! 따라서 digitNames뒤에 !를 붙여줍니다.)

 

 

함수가 여러개의 클로저를 가지고 있다면 첫번째 후행 클로저의 인수 라벨을 생략하고 남은 후행 클로저의 라벨을 표기합니다.

func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
    if let picture = download("photo.jpg", from: server) {
        completion(picture)
    } else {
        onFailure()
    }
}

completion과 onFailure의 두개의 클로저를 가지고 있는 모습입니다.

completion은 사진을 다운로드 한후 보여주는 완료처리이고,

onFailure는 오류를 표시하는 오류 처리기 입니다.

 

 

캡처값

클로저는 정의된 둘러싸인 컨텍스트에서 상수와 변수를 캡처(capture)할 수 있습니다? (캡처를 알아봐야 겠습니다,)

 

"개발자 소들의"님의 블로그에서 발췌한 내용입니다.

func doSomething() {
    var num: Int = 0
    print("num check #1 = \(num)")
    
    let closure = {
        print("num check #3 = \(num)")
    }
    
    num = 20
    print("num check #2 = \(num)")
    closure()
}

(클로저는 Value/Reference 타입에 관계없이 캡쳐하는 값들을 참조함!! 이것을Reference Capture라고 함)



클로저는 num을 캡처합니다! 즉 num이란 변수를 참조 한다고 합니다.

클로저를 실행하기 전에 num이란 값을 외부에서 변경하면 클로저 내부에서 사용하는 num의 값또한 변경됨!!

 

(다시 document로...)

Swift에서 값을 캡처할 수 있는 간단한 클로저 형태는 다른 분문 내에 작성하는 중첩함수 입니다. 

중첩함수는 바깥 함수의 어떠한 인수도 캡처할 수 있고, 바깥 함수 내에 정의된 상수와 변수를 캡처 할 수 있습니다.

(이해가 조금 어려우니 예제를 보면서 이해하겠습니다!)

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

incrementer는 중첩함수로 makeIncrementer함수의 내부에 정의되어 있습니다.

incrementer()함수는 둘러싸인 컨텍스트에 runningTotal과 amount값을 캡처합니다. 이값을 캡처한 후 incrementer는 호출할때마다

amount로 runningTotal을 증가시키는 클로저로 makeIncrementer에 의해 반환됩니다.

makeIncrementer의 반환타입은 () -> Int 입니다. 이것은 함수를 반환한다는 의미입니다!


incrementer() 함수는 파라미터가 없으며 함수 본문 내에 runningTotal 과 amount 를 참조하고 있습니다. 둘러싸인 함수에 runningTotal 과 amount 대한 참조 (reference) 를 캡처하고 함수 내에서 사용합니다. 참조를 캡처하는 것은 makeIncrementer 호출이 종료될 때 runningTotal 과 amount 가 사라지지 않고 다음에 incrementer 함수가 호출될 때 runningTotal 을 사용할 수 있습니다.

 

func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
}

단독으로 보면 incrementer 함수는 비정상적으로 보일 수 있습니다.

incrementer 함수는 파라미터가 없으며 함수 본문 내의 runningTotal과 amount를 참조하고 있습니다.

runningTotal과 amount에 대한 참조(reference)를 캡처하고 함수 내에서 사용합니다!
참조를 캡처하는 것은 makeIncrementer호출이 종료될 때 runningTotal과 amount가 사라지지 않고 다음에 incrementer함수가 호출될때 runningTotal을 사용할 수 있습니다!!

 

 

클로저는 참조 타입

참조하는 클로저는 캡처한 runningTotal을 계속 증가시킬수 있는 이유는 함수와 클로저가 참조타입(reference tpyes)이기 때문입니다!

 

뒷부분은 ARC를 공부한후 다시오도록!
- 엡! 삐~

 

 

생각과 감정

이전엔 졸업까지 별로 남지 않아 마음이 많이 조급했던것 같습니다! 흠... 다른분들에게 조언을 받고 여러 유튜브 영상을 보아도 천천히 자기페이스에 맞춰서 공부하는게 모쪼록 도움이 크다고 했지요.. 하하 저도 천천히 저의 페이스에 따라 나아가려 합니다!!

iOS개발자가 되는 그날까지 크흡... 화이또..!  

 

앞으로의 계획선언

ARC와 캡처, 탈출클로저에 대해 더욱 자세하게 알아봐야 겠습니다!!

 

 

 

 

https://babbab2.tistory.com/83

 

Swift) 클로저(Closure) 정복하기(3/3) - 클로저와 ARC

안녕하세요 :) 소들입니다! 이번 포스팅은 클로저 정복하기 마지막 편!!! 메모리나 ARC에 대한 사전 지식이 없으면 조금 이해하기 어려울 수 있으니, 메모리 관련 포스팅을 먼저 보고 오심을 추천

babbab2.tistory.com

 

'TIL' 카테고리의 다른 글

TIL_20230921  (0) 2023.09.21
TIL_20230918  (0) 2023.09.18
TIL_20230914  (0) 2023.09.14
TIL_20230912  (0) 2023.09.12
TIL_20230911  (0) 2023.09.11

어찌저찌 우리의 졸업작품 프로젝트가 끝났다... 

2022.07 ~ 2023.05까지 약 1년간 진행했다...

여름 방학때부터 매주 모여 아이디어를 회의하고 사실 지금의 아이디어는 찐찐찐찐막 의 아이디어를 선정 하였다 ㅋㅌㅋ

그렇게 아이디어중 하나를 선택하고 서로의 공부 방향을 정했다.

처음에 라즈베리파이로 서버를 열려 하였지만... ip가 유동ip여서 정말 불편했다는... 그리고 모델 연산을 하게되면 엄청난 부하로 인해 라즈베리파이 cpu로 고기도 구워먹을 수 있었다.

따라서 우리는 AWS를 사용하게 되고 뭐 이런저런 과정을 겪게 됐다 ㅋㅋ

아마 전공 4년동안 가장 인상적인 팀 프로젝트가 아닌가 싶다. 사실 이전의 것들은 하난도 인상적이지 않아 기억이 없다 ㅋㅌ

 

내가 앱 제작을 맡아 앱 개발 과정을 이 블로그에 올리려 하였지만 여러가지 문제로 인해 올리지 못했다. (주로 귀차니즘) 돌아보니 간단히 우리의 기능을 보여주려 하여다보니 앱 이라고 말하기 조금 꼬름해졌다 ㅋㅋ 

계획은 거창하였으나 구현을 못한것에 대해 아쉽다.. 로그인 뭐 회원관 등등의 기본적인 기능들도 넣었어야 하는 아쉬움.... 이 있다!!

그래도 이 이후에 계속 고쳐나갈 예정이니까 git주소 올릴태니 모두들 많관부 ㅎ 이쁘게 봐주세요 여루분  혹여나 간단한 프로젝트를 우리와 비슷하게 하려는 분들 참고하시구 인사팀 또는 관련 사장님들 우리 써주세요 ㅎㅎ 일 열심히해요 ㅎㅎ ㅋㅌㅋ 

 

 

 

 

 

 

 

 

(고생많았구 다들 음 팀장직은 이만 내려놓겠다. ㅋㅌㅋ )

 

 

https://github.com/NewP1/Golden_Time

 

GitHub - NewP1/Golden_Time

Contribute to NewP1/Golden_Time development by creating an account on GitHub.

github.com

 

 

수 찾기 성공

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 154089 45592 30312 29.849%

문제

N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.

예제 입력 1 복사

5
4 1 5 2 3
5
1 3 7 9 5

예제 출력 1 복사

1
1
0
0
1

출처

알고리즘 분류

 

코드

import Foundation

//N(1 ≤ N ≤ 100,000)
//M(1 ≤ M ≤ 100,000)

let N = Int(readLine()!)!
var arr_N = readLine()!.split(separator: " ").map{ Int($0)! }

let M = Int(readLine()!)!
var arr_M = readLine()!.split(separator: " ").map{ Int($0)! }

for i in 0..<N{
    let num_m = arr_M[i]
    if arr_N.contains(num_m){
        print(1)
    }else{
        print(0)
    }
}

너무 쉽다고 생각한후 이렇게 코드작성을 하니 당연히 시간 초과가 났다,,,

카테고리에 이진탐색을 발견후 코드를 바꿔줬다.

 

제출코드

import Foundation

//N(1 ≤ N ≤ 100,000)
//M(1 ≤ M ≤ 100,000)

func binarySearch(_ arr: [Int], _ target: Int) -> Int{
    var start = 0
    var end = arr.count - 1

    while start <= end {
        let mid = (start + end) / 2
            if arr_N[mid] == target {
                return 1
            }else if arr_N[mid] > target {
                end = mid - 1
            }else if arr_N[mid] < target {
                start = mid + 1
            }
        }
        return 0
}

let N = Int(readLine()!)!
var arr_N = readLine()!.split(separator: " ").map{ Int($0)! }

let M = Int(readLine()!)!
var arr_M = readLine()!.split(separator: " ").map{ Int($0)! }

arr_N.sort()

for i in 0..<M{
    print(binarySearch(arr_N, arr_M[i]))
}

'iOS > 백준' 카테고리의 다른 글

Swift 백준 10866번) 덱  (0) 2022.08.15
Swift 백준 10854번) 큐  (0) 2022.08.15
Swift 백준 2751번) 수 정렬하기 2  (0) 2022.08.09
Swift 백준 10989번) 수 정렬하기 3  (0) 2022.08.09
Swift 백준 2231번) 분해합  (0) 2022.08.08

수 정렬하기 2 성공

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 256 MB 203223 57808 39987 30.397%

문제

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

출력

첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.

예제 입력 1 복사

5
5
4
3
2
1

예제 출력 1 복사

1
2
3
4
5

출처

코드

import Foundation

let N = Int(readLine()!)!
var arr = [Int]()

for _ in 0..<N {
    arr.append(Int(readLine()!)!)
}

var resArr = arr.sorted()

for i in 0..<N{
    print(resArr[i])
}

'iOS > 백준' 카테고리의 다른 글

Swift 백준 10854번) 큐  (0) 2022.08.15
Swift 백준 1920번) 수 찾기  (0) 2022.08.10
Swift 백준 10989번) 수 정렬하기 3  (0) 2022.08.09
Swift 백준 2231번) 분해합  (0) 2022.08.08
Swift 백준 10828번) 스택  (0) 2022.08.05

+ Recent posts