하지마이씌

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
✅ Rx음미

 

우리 성태 이름 불러주세요~

 

후..  마지막 작성일이 07.08 입니다 ㅋㅋ,,,,.,.,. 그동안 많은 일들이 있었습니다..
3월부터 시작한 멋사 iOS 앱스쿨이 9월 추석전에 끝났습니다..허허 6개월간 많은걸 배웠네요 (오늘 글은 이 부트캠프 후기 아님! 후기도 안쓸거임!)

것보다 요즘 취업준비를 한창 하고있습니다만,, 자격요건이나 우대사항에 RxSwift나 Combine등등이 많이 있더라구요

그래서~~ rx를 공부를 시작한건 아니고.. 마지막 프로젝트에서 MVVM패턴을 채택해 팀원들과 개발을 했었는데,, 

MVVM으로 안만들고 유사 MVP패턴으로 개발을 했었걸랑여 ^_^ 그래서 리팩토링을 하기 전에 제가 스킬업을 해야 조금더 좋은 코드를 작성하고 팀이 채택했던 패턴으로 진행할수있을것 같았어요,,,,훠훠 

 

아 또있다.

그 RxSwift를 공부하기전에 사실 Combine을 먼저 배우고 하려했는데, 핑계를 대보자면,, 다른분들의 설명을 보아도 RxSwift를 알고있다는 기반으로 설명을 많이들 하시더라구요 그래서 저도 가족이 되고자 공부를 시작했습니다 ^_^

(아직 많이 한건 아니니까 그냥 읽으쇼)

 

배운점

자료를 찾아보면 RxSwift를 Cocoapods를 사용해서 먼저 프로젝트를 만들더라구요. 그래서 저도 오랜만에 pod init으로 pod파일을 만들어 보려 했지만! 

Searching for inspections failed: undefined method `map' for nil

 

터미널에 위와같은 경고를 보여주며.. pod init을 하지도 못한채 3시간쯤을 이 에러 해결을 위해 힘썼습니다..

 

그래서 해결했냐구요? 아니요.. 이것저것 깃 이슈들을 들추면서 코코아팟 재설치 뭐 루비 재설치 등등 brew까지 재설치했었어요 ㅎㅎ

하지만 안되더라구요..? 

pod install을 해서 워크스페이스 파일까지 만들었지만 워크스페이스안의 프로젝트가 보여지지않았고,, 터미널에 비슷한 경고 메세지를 보여줬었네요..

 

pod install로 안되면 뭐 어쩌겠습니까 ㅋ

그래서 저는 SPM을 사용해서 RxSwift를 적용했습니다.

 

다시 RxSwift로 돌아와서.

RxSwift 사용 이유

가장 먼저 RxSwift를 사용해야 하는 이유는 뭘까요?? 

저는 일단 스킬업을 하기위해서,,, 는 아니구 제가 아직 응용까진 많이 해보진 않았지만 코드가 깔끔해진다는 장점이 있었던것 같아요, 
예를들어 뭐 delegate나 NotificationCenter를 사용하지 않아도 되니까 ㅎㅎ

찾아보니 사용 이유는 

  • 명확하고 명시적으로 비동기 데이터를 처리한다.
  • 코드가 깔끔해지고 스레드 관리가 용이해진다.
  • TDD에 적용하기 좋다.

정도가 있는것 같습니다.

주요 개념

 

 ReactiveX의 사이트에 들어가보시면 Docs의 카테고리는

Observable, Operator, Single, Subject, Scheduler로 총 5개로 나누어져 있더라구요.

물론 다 알면 좋지만 저는 Observable, Operator, Subject를 주로 학습했습니다.

 

 

 

 

Observable

관찰 가능한 데이터 스트림인 Observavle입니다. 스트림은 하나의 흐름? 파이프? 라고 생각을 했습니다.

이벤트를 내보내고, 해당 이벤트에 반응하는 Observer가 그 이벤트를 처리합니다.

 

Observer

관찰자인 Observer 입니다. Observer는 Observable를 구독(Subscribe)하여 데이터 스트림을 감지하고,

새로 방출되는 값을 받아 처리합니다.

Operator

연산자인 Operator는 데이터 스트림을 필터링 하는데 사용됩니다.
Operator Docs 에 보시면 정말 많은 연산자들이 있습니다.

위 사이트의 "A Decision Tree of Observable Operators" 을 보시게 되면 어떠한 상황에서 사용해야할 연산자들을 알려주고 있습니다.

굉장히 친절하죠??

제가 간단하게 실습해본 연산자의 코드를 보여드리겠습니다.

@IBAction func exJust() {
    Observable.just(["Hello", "World"])
        .subscribe(onNext: { arr in
            print(arr)
        })
        .disposed(by: disposeBag)
//        ["Hello", "World"]
}

위의 코드는 "just" 연산자를 보여주는 코드 입니다.

Doc에선 just와 같은 연산자들을 "Creating Observables" 이라 칭하고 새로운 Observable을 만드는 연산자 라고 합니다.

 

 

@IBAction func exFrom1() {
    Observable.from(["RxSwift", "In", "4", "Hours"])
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
//        RxSwift
//        In
//        4
//        Hours
}

위의 코드는 Creating Observables중 하나인 from 입니다. 

 

똑같이 구독하여 print했지만 just는 ["Hello", "World"]를 출력하고 from은 한줄씩 출력되고 있습니다.
이 둘의 차이는 뭘까요? just는 모두생성 from은 한개씩 생성하는걸까요?

이는 docs의 마블 다이어그램을 보시면 이해가 됩니다.

 

 

뭐 print의 출력값으로 대강 예상을 했지만 doc에서도 이 차이를 알려주고 있습니다.

Just는 From과 비슷하지만, From은 배열이나 이터러블 등으로 들어가서 항목을 가져오는 반면, Just는 배열이나 이터러블 등을 변경하지 않고 단일 항목으로 그대로 방출한다는 점에 유의하세요.

 

이처럼 Docs를 보며 간단하게 연산자를 공부해보았습니다.

이외에도 위는 just와 from은 생성 연선자 이고,

생성 이외의 변환, 필터링, 결합, 유틸리티 등등 여러개의 연산자가 있습니다. 시간날때 들려서 확인하세요 ㅎㅎ 
(맨밑의 git에 간단하게 많이 사용한다던 연산자를 정리해두었습니다.)

DisposeBag

RxSwift에서 Observable을 구독하고 난 뒤 더이상 필요하지 않으면 구독을 해제해야 합니다.

DisposeBag에 dispose들을 담아 메모리 누수를 방지합니다.

var disposeBag: DisposeBag = DisposeBag()

@IBAction func onLoadImage(_ sender: Any) {
    imageView.image = nil

    let disposable = rxswiftLoadImage(from: LARGER_IMAGE_URL)
        .observeOn(MainScheduler.instance)
        .subscribe({ result in
            switch result {
            case let .next(image):
                self.imageView.image = image

            case let .error(err):
                print(err.localizedDescription)

            case .completed:
                break
            }
        })
        .disposed(by: disposeBag)
//        disposeBag.insert(disposable)
}

@IBAction func onCancel(_ sender: Any) {
    // TODO: cancel image loading
    disposeBag = DisposeBag()
}

 

 

후기

오늘은 여까증 작성해볼게요.. 진짜 신기한게 document나 유튜브 영상으로 해당 개념을 학습하고, 그 지식을 바탕으로 응용 코드를 작성해보고, 블로그 작성까지 해가면 개념이 더욱 머리에 잘들어오네요 훠훠.

간단한 응용코드를 작성했는데, API사용이나 MVVM패턴에 적용 등등을 더욱 학습해와 다시 포스트를 해보겠습니다 ^^

 

이후 예고를 하자면 rx가 끝나면 Pin&Flex Layout을 맛볼게요 ㅎㅎ

 

 

 

 

 

 

참고: https://www.youtube.com/watch?v=w5Qmie-GbiA&t=7577s

github: https://github.com/jjwon2149/RxSwift/blob/main/RxPrac/RxPrac/ViewController.swift

ToDo
✅ 조금은 부지런해진 나
✅ 감사해 🙏

 

매일 나태해 지는 나를 어떡하면 조금 부지런하게 살아갈수 있을지를 고민하던중

공부하는 환경을 바꾸기로 했습니다..하하 

바로 스터디 카페에 출첵을 하는것이죠!

이제 시간도 정해서 매일 오는 것으로 합시다 하하.하..ㅎ..ㅇ..

 

배운점

강의를 들으며 AppDelegate에 있는 코드를 뜯어보고있었습니다.
눈에 안들어오는 document까지,,

//SQLite DB
lazy var persistentContainer: NSPersistentContainer = {

    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {

            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    //context는 git의 스테이징area와 바슷
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {

            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

 

 

1. persistentContainer 변수.

- NSPersistentContainer는 데이터 모델과 저장소를 관리합니다.

- lazy var로 선언되며 처음 접근할때만 초기화됩니다.

- loadPersistentStores를 호출하여 데이터모델을 로드하고 영구 저장소를 설정합니다.

 

2. saveContext 함수

- saveContext함수는 데이터 변경을 저장소에 반영하는 역할을 합니다.

- viewContext는 github의 스테이징 영역과 유사한 개념으로 데이터를 변경하고 업데이트 할 수 있는 영역이다.

- context.hasChanges를 통해 현제 컨텍스트에 변경 사항이 있는지 확인하고, 변경사항이 있을경우

context.save()를 호출하여 저장소에 변경을 저장합니다.

 

 

 

CoreData CRUD

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

context를 AppDelegate의 persistentContainer로 부터 가져와서 사용한다.

 

- Create

let newItem = Item(context: self.context)
newItem.title = textField.text!
newItem.done = false
newItem.parentCategory = self.selectedCategory //Item과 Category의 정보저장
self.itemArray.append(newItem)

self.saveItems()

 

새로운 Item 객체를 생성합니다.

이 객체가 데이터에 할당된 후에 context.save()를 통해 CoreData에 저장됩니다.

 

-Read

    func loadItems(with request: NSFetchRequest<Item> = Item.fetchRequest(), predicate: NSPredicate? = nil) {
        do {
            itemArray = try context.fetch(request)
        } catch {
            print("Error fetching data from context \(error)")
        }
    }

loadItems메서드는 CoreData에서 데이터를 가져와 itemArray에 할당합니다.

NSPredicate를 통해 득정 조건에 따라 데이터를 필텉링합니다.

 

-Update

//MARK: - TableView Delegate Method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    itemArray[indexPath.row].done = !itemArray[indexPath.row].done

    //DB에 저장
    saveItems()
}

func saveItems() {

    do {
        try context.save()
    } catch {
        print("Error saving context \(error)")
    }

    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
}

itemArray[indexPath.row].done = !itemArray[indexPath.row].done
으로 변경이 된다.

context.save()로 변경사항을 DB에 저장한다.

 

-Delete

//context delete부터 먼저 제거해야함!
context.delete(itemArray[indexPath.row])
itemArray.remove(at: indexPath.row)

삭제시에는 context.delete에 삭제될 객체를 넣어주어야 context에 삭제사항이 반영된다.

context에 삭제사항을 반영하고 객체를 삭제하는 순서로 이루어져야함!

 

 

 

 

 

 

https://inuplace.tistory.com/1005

 

[CoreData] 기초개념 (1): Entity, CRUD

CoreData란? Apple에서 제공하는 데이터관리 프레임워크로, 데이터를 유지 및 캐싱할 수 있을 뿐 아니라 Cloudkit을 사용해 여러 장치에 데이터를 동기화하는 것도 가능하다. 내부적으로 SQLite를 사용

inuplace.tistory.com

https://80000coding.oopy.io/72aca705-64d9-4be6-aaf5-34c1def4223a

 

(Swift) 코어 데이터 이해하기

"아래 모든 내용은 애플 공식 문서를 참고하여 정리 및 구현한 내용입니다."

80000coding.oopy.io

생각과 감정

오늘까지 졸업유예기간이다.. 유예는 하지 않겠다,,, wOO yEaH~,,,,

 

'TIL' 카테고리의 다른 글

TIL-Vapor 맛보기  (1) 2025.01.16
TIL_20241009 Rx를 곁들인..  (0) 2024.10.09
TIL_20240116 iOS에서 데이터를 저장하는 방법  (0) 2024.01.16
TIL_20240110 Swift_AppSandbox, NSCoder  (0) 2024.01.10
TIL_20240109 Swift_SingletonPattern  (0) 2024.01.09

ToDo
✅ 운동
✅ 취지직...준비 
✅ 공부

 

글을 쓴지 조금 지났군요 하하 ^_^ 갑작스레 잡힌 면접을 준비하느라 공부는 살짝 미뤄뒀습니다.

솔루션 회사에 면접을 보고왔습니다만,, 여러 느낌은 제껴두고 면접관님에게 감사한 느낌이 듭니다. 

물론 합불을 떠나서 개발자로써 좋은 조언들을 해주시고 분위기도 편안하게 해주셔서 너무 감사드려요 ^_^/

하지만 저는 손에 땀이 너무 많이나더군요 하하.. 긴장했는지 발을 살짝 떨었는데 들킨거같은 느낌ㅋ

 

하튼~ 취준을 할때마다 느끼는 거지만 생각을 하면 할수록 머리가 복잡해집니다..~~

그래서 이제부터 스터디 카페에서 공부를 하려구요..ㅎ

타자를 좀 우다다다 치고싶지만 다른 공부하시는 분들을 위해 살살 누르는중..ㅋ

 

마저못한 CoreData와 데이터를 저장하는 방법들을 후다닥 알아봅시다~

 

배운점

UserDefaults

- 정보를 저장하고 검색하는 가장 일반적이고 편안한 방법

- 사용자 기본설정인 작은 정보 (ex. dark or ligh mode, volume크기(소리) 등) 를 저장할때 사용.

- 일반적으로 앱에 설정 화면이 있는 경우 UserDefaults가 적합

- 이는 Key-Value 로 property plist 또는 plist로서 disk에 저장된다.

- AppData > Library > Preferences 안에 plist 파일이 있는데 이게 표준 UserDefaults의 database 파일

 

Keychain

- 이는 disk에 있는 특수한 파일

- 암호화하고 보안을 유지해야 하는 작은정보 (ex. 암호, 자격증명, 토큰 등) 를 저장할때 사용

- 모든 것이 Data로 저장되어야 함. 따라서 해당 유형으로 직렬화 할 수 있는 object와 value만 전달해야함.

- 참고로 Keychain Sharing 을 활성화하려면 keychain에 저장한 값을 같은 팀에서 개발한 다른 앱과 공유 가능.

- ( 실제로 앱에서 키체인을 사용하려 한다면 좋은 라이브러리를 검색하여 그 라이브러리가 대신 작업을 해야 시간과 스트레스에 도움이 된다합니다 ^_^ 

 

File Sytem

- 저장해야하는 항목이 UserDefaults, Keychain에 해당하지 않는 경우 파일시스템 사용.

- 컴퓨터의 파일 시스템과 똑같이 작동하며, 경로와 URL을 사용하여 디스크의 리소스를 식별.

- 암호화 해야 하지만 키체인에 저장할 수 없는 대용량 파일의 경우 파일에 쓸 때 적절한 암호화 옵션을 사용하는 것이 좋음.

- 사용자의 진행 상황을 저장하기 위한 파일을 Library 폴더에 만들 수 있음.

- 앱의 파일 시스템은 샌드박스 처리됩니다. (링꾸)

 

언제사용?

- 웹에서 다운로드 한 이미지를 저장해서, 로딩 시간을 단축할 때는 Library/Caches 폴더 사용

- 앱에서 사용자가 콘텐츠를 만들 수 있도록 허용하는 경우 Document 폴더 사용 (ex. 사용자가 내보낼 수 있는 CSV 파일의 위치)

다만 동영상과 사진을 편집하는 경우 CameraRoll이 더 나은 선택.

 

sqlite

- 데이터를 저장하는 장소 이상으로 내부 데이터베이스의 사실상 표준.

- Library 폴더는 일반적으로 SQLite 데이터베이스를 저장하기에 가장 좋은 장소.

- 잘 구조화된 수많은 데이터가 있을때 사용하기 좋음

- 스토리지 기능 외에도 SQL 데이터베이스가 있으면 효율적인 검색이 가능하고 복잡한 쿼리를 작성하여 흥미로운 인사이트를 얻을 수 있음

 

CoreData

- Core Data는 iOS가 제공하는 ORM (Objected - Relational Mapping) 프레임 워크

- 데이터를 저장하고 관리하기 위한 프레임워크 즉 데이터를 조작하는 방법

- CoreData는 해당 기기에 데이터를 저장하므로 오프라인에서도 동작 가능하며,icloud에 데이터 공유 가능.

- SQL을 쓸 일 없이 오롯이 object - oriented 방식으로만 데이터를 다룰 수 있음. 데이터는 Object로 표현되며, 이러한 Object가 관계를 형성하어 Object Graphs를 이루고 이를 관리하는 프레임 워크가 바로 Core Data

- CoreData도 내부적으로는 SQL을 이용하여 데이터를 저장하지만, 개발자는 Xcode에 내장된 데이터 모델 에디터를 통해 데이터의 타입, 관계(Graphical Relationship)를 지정하고 코드로 관련 클래스를 수정할 수 있음.

- 우리는 Context에 의해 관리되는 DataModel을 만듦. 그리고 Context는 데이터 저장 및 검색을 담당하는 StorePresistor와 상호작용함.

- 여러 엔티티와 관계가 있는 복잡한 오브젝트 모델을 추적해야 할 때 좋음

- SQLite보다 더 빠르게 기록을 가져올 수 있지만, 더 많은 메모리와 저장 공간을 사용.

 

 

앞으로의 계획선언

CoreData부분은 더욱 알아봐야 할 것 같습니다. (persistentcontainer, context)등 아직 이해가 덜된것이 많군요

 

https://betterprogramming.pub/5-ways-to-store-user-data-in-your-ios-app-595d61c89667

 

5 Ways To Store User Data in Your iOS App

Choose the right storage based on your requirements

betterprogramming.pub

https://github.com/sujinnaljin/TIL/blob/master/Swift/5%20Ways%20To%20Store%20User%20Data%20in%20Your%20iOS%20App.md

https://80000coding.oopy.io/72aca705-64d9-4be6-aaf5-34c1def4223a

 

'TIL' 카테고리의 다른 글

TIL_20241009 Rx를 곁들인..  (0) 2024.10.09
TIL_20240119 iOS)CoreData로 부숴지기.. CRUD  (0) 2024.01.19
TIL_20240110 Swift_AppSandbox, NSCoder  (0) 2024.01.10
TIL_20240109 Swift_SingletonPattern  (0) 2024.01.09
TIL_20240103  (0) 2024.01.05

ToDo
✅ 운동
✅ 공부

어제 하루 루틴을 조금 예상해보았지만.. 한두시간씩 밀리는 감이 있습니다 하하..

호다닥 공부를 해보겠습니다.

 

배운점

공부를 조금 진행하면서 간단한 앱을 만든적이 있습니다.

ToDoApp입니다. 하하

이 앱을 만들던중, 오늘 할일과 할일을 체크하는 두개의 기능이 있었지만, 앱을 껐다 키면 데이터가 모두 날아가,

UserDefaults를 사용해서 데이터를 저장하였습니다.

하지만 데이터를 저장하고 불러오는것은 성공하였지만, Todo의 체크여부가 셀이 늘어날수록 엉키고, 셀을 삭제했을때도 순서가 맞지않는 문제를 겪어, 체크박스를 커스텀해 제작을 했습니다!

 

하지만 공부를 하던중 이 이유를 알았습니다.. 바로 ReusableCell 때문이더군요! 테이블뷰를 스크롤 하여 내리면 새로 생기는 셀이 스크롤하며 보이지 않는 셀로 재활용 되어 나타나 체크가 되어있는 이슈였습니다.. 하하

이걸 알았다면 체크박스를 직접만드는 삽질은 안해도,, 또한 UserDefaults는 작은 정보만 저장을 하도록 추천을하고 UserDefaults 싱글톤으로 관리됩니다. 또한 UserDefaults를 사용하면 기본 자료형의 딕셔너리만 사용 할 수 있습니다.

따라서 데이터를 저장하는 방법을 NSCoder를 사용하여 바꾸었습니다. 


데이터를 plist로 저장하고 불러오기를 하기전 Sandbox의 개념을 알아보았습니다.

 

App Sandbox

: 앱이 손상된 경우 손상을 방지하기 위해 macOS 앱의 시스템 및 사용자 데이터에 대한 엑세스를 제한합니다.

 

프로그램을 보호하는 보안 모델로 보입니다!

 

 

 

앱을 다운받아 실행하면 이러한 화면을 많이 접합니다.

또한 Sandbox는 커널수준에서 시행되는 접근 제어 기술 이라고 합니다.

 

커널?? 메모리에 상주하는 운영체제의 부분

소프트웨어가 컴퓨터에서 실행되기 위해서는 메모리에 그 프로그램이 올라가있어야 합니다.

전원을 키자마자 OS또한 메모리에 올라갑니다.
하지만 OS 매우 커서 필요한 부분부분을 올리게 되는데 이때의 영역을 커널 이라고 합니다.

 

 

 

 

 

 

왼쪽 그림이 샌드박스가 없는 것이며 오른쪽은 샌드박스를 사용하는 앱의 경우 입니다.

 

왼쪽의 경우

앱을 실행하는 사용자는 모든 권한을 가지며, 사용자가 접근할 수 있는 모든 리소스에 접근을 할 수 있게 됩니다.

이는 보안의 허점이 있을 경우 앱의 취약점이 공격당할 수 있으며 공격자는 사용자가 수행할 수 있는 모든 작업을 수행할 수 있게 됩니다.

아주 악용하기 너무 좋아보이는걸요??

 

따라서 보안뿐 아닌 접근 문제또한 해결하기 위해 AppSandbox를 사용하는것 입니다.

 

1. AppSandbox를 사용하면 앱이 시스템과 상호작용 하는 방식을 설명합니다. ( 접근 권한을 앱에 부여하는것)

2. AppSandbox룰 사용하면 갤러리, 열기, 저장 등등 사용자 상호작용을 통해 앱에 투명하게 추가 접근 권한을 부여합니다.

 

App Sandbox의 원칙

:  App Sandbox는 각 앱마다 취약한 리소스에 대한 액세스를 제한함으로써 공격자로 인한 사용자 데이터 도난, 손상 또는 삭제 또는 시스템 하드웨어 해킹에 대한 마지막 방어선을 제공합니다.

하드웨어, 네트워크 연결, 앱 데이터, 사용자파일 등과 같은 리소스를 사용하기 위해서는 그 의도를 명시해야 합니다.

 

App Sandbox의 구조

샌드박스는 위와같은 내부 컨테이너로 볼 수 있습니다.

샌드박스에는 여러 디렉토리가 포함되어 있습니다.

 

Bundle Countainer

이곳은 앱의 번들 입니다. 이 디렉토리에는 앱 바이너라와 앱에서 사용되는 모든 리소스가 포함되어 있습니다.

이 디렉토리에는 write를 할 수 없습니다. 이 디렉토리에 write를 하면 서명이 변경되어 앱이 실행되지 않습니다.

(API를 사용하면 앱 번들에 저장된 모든 리소스에 대한 읽기 전용 액세스 권한을 얻을 수 있습니다.

 

DataCountainer

사용자가 텍스트 이미지 등을 저장하고 앱의 런타임 중에 생성된 데이터등 앱의 데이터를 저장합니다.

 

Document : 이 디렉토리를 사용하여 사용자 생성 콘텐츠를 저장합니다.

(iCloud를 사용하여 백업 가능)

 

Libary : 사용자 데이터 파일이 아닌 모든 파일의 최상위 디렉토리 입니다.

 

Temp : 이 디렉토리를 사용하여 앱 실행 간에 유지될 필요가 없는 임시 파일을 작성합니다.

(iCloud를 사용하여 백업 불가)

 

iCloud Container

런타임에 접근을 요청할 수 있는 추가 컨테이너 디렉토리입니다.

 

App Sandbox의 장점

- Sandbox는 앱의 데이터와 정보를 비공개 환경으로 보호하고 유지합니다.

- Sandbox는 시스템 리소스를 손상으로부터 보호함으로써 잠재적인 해커로부터 발생할 수 있는 피해를 최소화 할 수 있습니다.

- iOS or iPadOS 기기에 앱이 설치되면 시스템은 해당 앱에 대한 고유한 디렉토리를 생성합니다.

 

 

 


따라서 App Sandbox덕분에 앱이 수명 내내 파일에 저장된 데이터를 읽기,쓰기를 할수 있습니다.

 

 

ReusableCell을 사용하지 않기 위해 데이터 모델을 만들어주었습니다.

import Foundation

class Item: Codable {
    var title: String = ""
    var done: Bool = false
}

 

할일인 title과 체크여부를 알려주는 done을 작성하였습니다.

 

Codable을 사용하여 plist로 [Item]타입의 배열을 저장하려 합니다.

 

plist가 저장되는 장소는

let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("Items.plist")
print(dataFilePath)

위의 코드로 알 수 있습니다.

 

//    addButtonPreesed에서 plist를 저장하게된다면 title은 저장이됨, 하지만 done 즉 체크를 판단하는 부울은 저장이 안됨
//    이는 didSelectRowAt안에서또한 저장을 해야함. 따라서 같은 코드를 복붙X 함수를 만들어 사용
func saveItems() {

    let encoder = PropertyListEncoder()

    do {
        //데이터 인코딩
        let data = try encoder.encode(itemArray)
        //dataFilePath에 items.plist 생성
        try data.write(to: dataFilePath!)
    } catch {
        print("Error encoding item array, \(error)")
    }

    //테이블뷰에 itemArray의 내용의 셀을 보기위한 리로드
    self.tableView.reloadData()
}

//plist에 저장된 data 가져오기
func loadItems() {
    if let data = try? Data(contentsOf: dataFilePath!) {
        let decoder = PropertyListDecoder()
        do {
            //데이터파일 패스에서 데이터를 디코딩하는 메서드
            itemArray = try decoder.decode([Item].self, from: data)
        } catch {
            print("Error decoding item array, \(error)")
        }
    }
}

 

PropertyListEncoder와 PropertyListDecoder

PropertyListEncoder는 Encodable 프로토콜을 따르는 데이터 타입을 PropertyList형식으로 인코딩 할 수 있게 됩니다.

PropertyListDecoder는 반대로 Data를 Decodable 프로토콜을 따르는 타입으로 디코딩 할 수 있도록 해줍니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

https://medium.com/techiepedia/demystifying-ios-ipados-sandbox-with-swift-code-8c9222d19380

 

Demystifying iOS/iPadOS SandBox with Swift Code

Hello everyone in this article we are going to see what is iOS Sand Box and how does it works and how developers can access their app’s…

medium.com

https://developer.apple.com/documentation/security/app_sandbox#//apple_ref/doc/uid/TP40011183-CH1-SW1

 

App Sandbox | Apple Developer Documentation

Restrict access to system resources and user data in macOS apps to contain damage if an app becomes compromised.

developer.apple.com

 

생각과 감정

어.. 요즘 갑자기 모든것이 2배속으로 느껴질때가 있더군요 검색을 해보니 스트레스 때문이라던가~ 저는 아니라고 생각해왔지만

막상 받긴 받나 봅니다 허허,, 구래도 정진... 해야겠지..?

부지런하려 노력한 나에게 감사해...🙏

 

 

'TIL' 카테고리의 다른 글

TIL_20240119 iOS)CoreData로 부숴지기.. CRUD  (0) 2024.01.19
TIL_20240116 iOS에서 데이터를 저장하는 방법  (0) 2024.01.16
TIL_20240109 Swift_SingletonPattern  (0) 2024.01.09
TIL_20240103  (0) 2024.01.05
TIL_20231226  (0) 2023.12.26

ToDo
✅ 운동 clear~
✅ 나태지옥 빠져나가기
✅ 졸업신청인가 유예인가?

✅ Swift singleton pattern 공부

 

후 오픽 점수를 IM2를 받아 졸업을 할수 있게 되었습니다만.....

과연 졸업을 하는것이 맞는것인가? 졸업유예를 하는것이 맞는것인가?? 허허..

어떻게 생각하시나요?

저는 아직 모르겠습니다만...

둘다 이후에 행적은 비슷할것 같지만 어떤것이 더욱 유리할까요~!~! 유리...라,,,,

이득? 흠... 뭐 비슷비슷 할것 같습니다만~!~

유예신청 기간에 생각좀 해보겠습니다..ㅎ

 

하루 루틴을 예상하고 내일부터 지켜보도록 하겠습니다. (자세한 일정은 추가하지 않는다.. 나는 극Pㄷ,,)

8시쯤 느지막하게 기상 후 식사

9시 운동출발

11시 집도착

12시 점식먹고

13시 유데미 강의 때리기 (틈틈히 쉬기)

16시 cs공부

18시 or 19시 저녁

~휴식

22시  인턴/신입 공고 구경 코테한문제 때리기?

24시 or 01시 취침

 

이렇게 보니 흠 너무 계획이 난장판이군요...

조금더 자세하게 정리하고 지켜나가 보겠습니다. 일단 저건 초안 ㅋ

배운점

UserDefaults를 이전에 간단한 TODO앱을 만들때 공부하였습니다만!

오늘 Udemy강의에서도 todo앱을 만들면서 싱글톤 패턴이 나와

싱글톤패턴을 공부해보았습니다..하하

 

싱글톤 패턴(Singleton pattern)

특정 용도로 객체를 하나만 생성하여, 공용으로 사용하고 싶을 때 사용하는 디자인 유형. 이라고 정의되어있습니다.

또는 한 개의 클래스로 만드는 객체는 단 한개여야만 한다는 규칙을 가진 디자인 패턴 입니다.

 

프로그램 전체에 단 하나의 전역 객체를 만들어놓고 다른곳에서 이 하나의 객체에 접근하는것 입니다.

 

EX)

URLSession.shared : 네트워크 처리를 할 때 URLSession 객체를 이용하는데, 이미 만들어져 있는 shared 객체에 접근해 메서드를 수행한다.

UserDefaults.standard : UserDefault에서 기본적으로 공유하고 있는 standard 저장소에 접근해 쓰고 읽기 위해 만들어져 있는 standard 에 접근해 메서드를 수행한다.

 

이 위 두예시가 싱글톤 패턴을 기반으로 만들어졌다고 생각하면 된다 합니다 ㅎㅎ

 

import UIKit

//Car 클래스는 빨간색 색상을 가지고, static let으로 만들어진 Car()의 객체인 singletonCar를 만듭니다.
class Car {
    var colour = "Red"
    
    //싱글톤 인스턴스를 저장하는 static상수
    static let singletonCar = Car()
}

let myCar = Car.singletonCar
myCar.colour = "Blue"

//인스턴스 공유 
let yourCar = Car.singletonCar
print(yourCar.colour) //yourCar도 같은 싱글톤 인스턴스를 참조하므로 "Blue"가 출력됩니다.

class A {
    init() {
        Car.singletonCar.colour = "Broun"
    }
}

class B {
    init() {
        print(Car.singletonCar.colour)
    }
}

let a = A()
let b = B()

//A클래스의 인스턴스를 생성하며 색상을 Brown으로 변경됩니다.
//B클래스의 인스턴스를 생성하면서 색상을 출력합니다. "Brown"출력

 

 

결과적으로 싱글톤 패턴을 사용하면 언제나 동일한 Car객체에 접근할 수 있으며, 객체의 상태를 전역적으로 관리할 수 있습니다.

위의 코드에서 볼 수 있듯이 여러 클래스에서 해당 싱글톤 인스턴스를 공유하고 상태를 변경할 수 있음을 보여줍니다.

 

위와같이 강의를 보며 싱글톤 패턴을 이해하였는데요! 

다른 블로그를 구경하며 다른 예제를 보며 이해를 도왔습니다.

 

class UserInfo {
    var id: String?
    var password: String?
    var name: String?
}

 

User의 정보를 저장하는 UserInfo라는 클래스를 선언합니다.

 

//A ViewController
let userInfo = UserInfo()
userInfo.id = "Sodeul"

//B ViewController
let userInfo = UserInfo()
userInfo.password = "123"


//C ViewController
let userInfo = UserInfo()
userInfo.name = "Sodeul"

 

A,B,C ViewController에서 각각의 UserInfo객체를 만들어서 저장하면,

각 인스턴스의 프로퍼티에만 저장이되며 데이터는 공유할 수 없게 됩니다.

 

따라서 UserInfo에 대한 인스턴스는 최초 생성될 때 딱 한번만 생성해서 전역으로 선언하고 이후에 이 인스턴스만 접근 가능하게하자

--> 이 말이 Singleton Pattern 입니다.

 

따라서 

class UserInfo {
    static let shared = UserInfo()

    var id: String?
    var password: String?
    var name: String?
    
    private init() { }
}

 

static을 이용해 인스턴스를 저장할 shared라는 프로퍼티를 생성합니다.

이후에 혹시 init를 호출해 인스턴스를 또 생성하는 것을 막기위해 init의 접근제어자를 private로 지정합니다.

 

위와같이 싱글톤을 만들수 있습니다.

 

외부에서의 접근은 

//A ViewController
let userInfo = UserInfo.shared
userInfo.id = "Sodeul"

//B ViewController
let userInfo = UserInfo.shared
userInfo.password = "123"
 
 
//C ViewController
let userInfo = UserInfo.shared
userInfo.name = "Sodeul"

 

어느 ViewController에서든 shared라는 프로퍼티에 접근하면 하나의 인스턴스를 공유합니다.

 

그럼 싱글톤패턴에 대해 알아봤으니 장/단점 또한 알아 보겠습니다 ㅎㅎ

 

싱글톤 패튼의 장/단점

장점

- 메모리를 단 한번만 사용한다.

해당 객체는 단 한번만 만들어지기 때문에 메모리 관리가 편하다는 장점이 있습니다.

 

- 객체 접근 시간이 줄어든다.

다시 메모리를 할당하고, 초기화(init)하는 시간이 줄어드니 한번 만들어 두기만 하면

다시 접근할 때 매번 객체를 만드는 것보다 조금이나마 시간이 빠르다.

 

- 전역 번위에서 상태, 데이터 전달이 쉬워진다.

어디에서든 접근할 수 있기 때문에 데이터를 전달할 수 있다.

 

단점

 

- 테스트가 힘들다.

싱극톤 클래스는 초기화를 private로 선언합니다.

이렇게 한다면 테스트용 Mock 객체를 만들어내기 어려워진다.

 

- 의존성을 만들어낸다.

어디에서나 접근을 할 수 있으니 어떤 객체와 연결되어 있는지 다 찾아내기 힘들어진다.

 

- 멀티 스레드 환경에서 위험할 수 있다.

멀티 스레드 환경에선 싱글톤 객체가 2개가 생기는 문제가 발생할 수 있다.

또한 싱글톤 객체 내부의 데이터를 동기적으로 처리하지 않으면 여러 객체가 동시에 사용되다 꼬여버릴수 있다.

 

 


테스트용 Mock 객체..?? 

: Swift에서 Mock 객체는 주로 단위 테스트를 수행할 떄 사용되는 가상의 객체라고 합니다!

이 객체는 실제 객체를 모방하여 특정 동작을 시뮬레이션 하거나 메서드 호출을 기록하고 검증하는데 사용된다 하군요.

주로 의존성 주입 패턴과 함께 사용되어 코드의 격리성을 유지하고 테스트 가능한 코드를 작성하는데 도움이 된다고 합니다.

(링크)

 

생각과 감정

생각과 감정이라.. 하하 위에서 다 말을 해버려서 훠훠

 

앞으로의 계획선언

이제 더는 학생이 아닐수도..? 하지만 배움엔 끝이없죠 매일 꾸준이 공부하다 보면 좋은 기회가 있을거라 생각합니다 ㅎㅎ

항상 열심히 정진 하겠습니다.

오늘만큼은 부지런했던 나에게 감사해...🙏

 

 

 

 

https://stackoverflow.com/questions/137975/what-are-drawbacks-or-disadvantages-of-singleton-pattern

 

What are drawbacks or disadvantages of singleton pattern?

The singleton pattern is a fully paid up member of the GoF's patterns book, but it lately seems rather orphaned by the developer world. I still use quite a lot of singletons, especially for factory

stackoverflow.com

 

https://babbab2.tistory.com/66

 

Swift) 싱글톤 패턴(Singleton Pattern)

안녕하세요 :) 소들입니다 이번 포스팅에선 싱글톤 패턴이 무엇이고, Swift에선 어떻게 사용되는지에 대해 알아보려고 해요!!! 왜 네트워크 하다가 갑자기 SingleTon이냐 하면 내 마음임 모든 포스팅

babbab2.tistory.com

 

https://medium.com/hcleedev/swift-singleton-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4-b84cfe57c541

 

Swift: Singleton, 싱글톤 패턴

Singleton 패턴은 무엇인지, 장단점을 알아보고, Semaphore를 이용한 사용 예시까지 살펴보자.

medium.com

 

'TIL' 카테고리의 다른 글

TIL_20240116 iOS에서 데이터를 저장하는 방법  (0) 2024.01.16
TIL_20240110 Swift_AppSandbox, NSCoder  (0) 2024.01.10
TIL_20240103  (0) 2024.01.05
TIL_20231226  (0) 2023.12.26
TIL_20231223  (0) 2023.12.23

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
✅ 운동
✅ OPIC 개노쥄..

 

30일에 오픽을 결제하고 미친 벼락치기를 하는중입니뒈....

토익은 시간이 조금 걸리니 졸업을 위한 벼락치기..ㅋㅋㅌ

잘못은 제가 많이했습니다.. 졔송함다...

 

배운점

 

오픽노잼님의 영상을 보며 꿀팁을 조금 흡수했습니다.

오픽노잼,,,

Im 시리즈 001

AVA : i would like to know where you live

  • describe your home
  • what does it looks like?
  • how many rooms does it have?
  • give me a description with lots of details.

학생 :

Oh, you wanna know about my palce? Ok.

bascially, i live in 4-story house.

this place very small place.

looks like, maybe… a shoebox?

so,,, but,,, this palce very, very comfortable and cozy because only focus me. focus to me.

And so, this place nearby university 공주.

very, very good. Favorite

so, i gruated university 공주.

so, this place very looks like,,, uh, like, i feel so comfortable.

That’s all

Rule 1. Ava에게 질문하지 않기. 질문할때는, 수사학적 질문으로.(대답이 필요없는 질문)

Oh, you wanna know about my palce? Ok. → 어색한 질문을 던짐

질문을 던지는것보단 인정하는것.

Oh, so you wanna know about my palce? Alright, well~

⇒ 상대방이 무언가를 원하고 있다는 것을 알아차리고 응답을 할때 사용한다.

Rule 2. 불편한 어려운 단어 사용하지 않기! 사용하기 편하고 간단한 단어 사용하기.

bascially, i live in 4-story house.

4-story house. 은 4층집.. ㅋ 어려운 단어를 잘못씀

⇒ my home is really small. 같이 간단한 단어 사용

(house는 apartment와 구별하는 단어 따라서 Home사용)

this place very small place.

⇒ this place 로 자신의 집이 아닌 느낌이 남.

따라서 it’s very small place, my place is a very small place 등 사용

Rule 3. 한문장에 같은단어 반복하지 않기.

this place very small place. : place를 두번 사용함

Rule 4. 무언가 묘사하거나 감정 단어를 2개이상 말할때 “AND” 사용하지 않기.

and를 사용하면 스크립트를 외워서 말하는것 같음.

한문장을 두문장으로 말하기.

so,,, but,,, this palce very, very comfortable and cozy because only focus me. focus to me.

⇒ my room is just so, you know, comfy. it’s mean cozy!

Rule 5. 한가지에 대해서만 말하기! (주제에서 벗어나지 않기.)

다른 이야기를 덧붓이거나 관련 없는 이야기는 흐름을 방해하므로 한가지 주제만 이야기 한다.

한가지 주제를 선택하고 1분동안 마인드 맵을 그리며 이야기한다.

And so, this place nearby university 공주. ~~ 주제에 벗어남.

Im 시리즈 002

자신이 IL 아니면 IM1 이다. ⇒ 3선택X 적어도 난이도 4이상을 선택!! 더높은 점수를 받을 확률이 높아짐.

AVA : What is your normal routin at home? (집에서 평소에 뭐하시나요?)

  • What thing do you usually do on weekdays and what kinds of things do you go on weekends? (평일과 주말엔 뭐하시나요?)

⇒ A 평일엔 뭐해? B: 주말엔 뭐해? A,B둘중 하나 선택후 ex) A 1% B 99% 대답하기!

학생 :

um, I’m a student so i spend time at library on weekdays, yeah.

you know, i didn’t have much time on weekdays.

but instead, i usually spend time at home on weekend, yeah.

i love this time because i can do everything what i want, yeah.

but you know what?

i love watch movies.

so, i usually watch movies at home.

if makes me flexed, yeah.

quite good. um.

the another thing is…

Um, you know, the another thing is listen to music, catch some z’s, and so on, yeah

these things are makes me full of energy.

⇒ A 평일엔 뭐해? B: 주말엔 뭐해? A,B둘중 하나 선택후 ex) A 1% B 99% 대답하기!

you know, i didn’t have much time on weekdays.

나는 평일 이야기 는 조금하고 주말만 이야기 하겠다, 그래도 평일 약간 설명하기.

  • Im barely home
  • Im rarely home
  • im like never home
  • i only come home to sleep

so, i usually watch movies at home.

( 덧붙이기)

And so, that is what i usually do at home at on weekends.

if makes me flexed, yeah.

⇒ it helps me to relax. it makes me feel so good to watch movies all day.

Um, you know, the another thing is listen to music, catch some z’s, and so on, yeah

Rule 2. 불편한 어려운 단어 사용하지 않기! 사용하기 편하고 간단한 단어 사용하기.

the another thing is…~~

Rule 5. 한가지에 대해서만 말하기! (주제에서 벗어나지 않기.)

를 어기고있음.

⇒ 긴장해서 다른이야기를 하거나 말이안나옴.

Rule 6. 긴장이 되고 할말이 없을땐, 바로 결론으로 말하기.

아무말이 안나오면 바로 결론으로 말하고 끝내기.

Hbit 카테고리에서 (how to talk more!)

아무말이 안나온다!

  • Quick comparison 빠른 비교

it helps me to relax. it makes me feel so good to watch movies all day.

이 문장 뒤에 진짜 말이 나오지 않는다면 결론으로 가기.

하지만 연습을 할땐 “Hbit”의 전략을 생각하기. (Quick comparison 빠른 비교)

빠른 비교 : 잠깐 과거로 갔다가 현재로 오는것,

ex) 예전엔 이랬지만 지금은 이렇다.

I never did this before, but nowdays, i just love doing this!

  • i just dont know why!, i just cant explain it!

more hard)

its funny… i never really did this before, but nowadays, i just love doing this

따라서 이학생은 Rule 2, 5, 6 를 어겼다..

Im 시리즈 003

AVA : describe the home you lived in as a child.

  • how was that home differnt from the home you live in now?
  • 어렸을때, 살았던 집에 대해 말해주세요.

학생 :

My childhood's home... Oh, actually I can't remember very specifically, but one thing I just remember very clearly it was so huge house.

Sofa, furnitures, chairs, desks... everything

was so huge. So big. It's feels like I was a ant. Because I think I was a little girl that's why l feeled like everything was so big.

Now, l'm live in more big house. But I'm still need more place. I feels it's not bigger than when I kid is. Oh, maybe I'm growing so that's why I feels like it.

Rule 7. “솔직한 변명”은 나중에 하기. 처음 부분에 하지 않기.

오픽 대답을 할때, 솔직하게 말하는 것이 훨씬 좋다.

선의의 거짓말 또한 좋다,

하지만 다른사람의 스크립트 외워서 하는건 비추 (거짓말 하는것이 더욱 어렵기 때문)

My childhood's home...

질문에 있는 단어를 말하면서 생각하는 모습을 보여줬다.

 

생각과 감정

초중고를 합하면 12년을 영어를 배웠지만,, 말을 잘못하네 내가..?하하

들리기는 하지만 입으로 잘 나오지 않고 생각하는 말이 뜻대로 전달이 안되는군요..

영어마스터 하는 그날까지.. 화이팅!!(그날이 언제임.?)

 

 

 

'TIL' 카테고리의 다른 글

TIL_20240109 Swift_SingletonPattern  (0) 2024.01.09
TIL_20240103  (0) 2024.01.05
TIL_20231223  (0) 2023.12.23
TIL_20231221  (0) 2023.12.21
TIL_20231212  (0) 2023.12.12

ToDo
✅ 운동
✅ 치즈케이크먹기 ㅋ

 

SwiftUI를 공부흐는 증읍느드.... uikit보다 재미가 느껴지네욤 아직 uikit은 마스터하진 못하였지만

흥미도 조금있어야 스트레스를 덜받겠죠 ㅎ.. 암튼~

곧 있으면 크리스마스네요 ^_^ 모두들 메리 크리스마스~~ (이브와 당일엔 등장하지 않습니다..)

 

배운점

https://simth999wrld.tistory.com/60

 

TIL_20231113

짧은인사, 하루의 사건, 나의 행동 ToDo ✅ udemy 완강 끄읕 ✅ 패캠 강의 ✅ 운동 가을은 어디갔죠...? 하ㅏㅎ... 날씨가 이리 추울 수 있나요ㅋㅋ 열어분 모두 감기 조심하세요~~ 또 건조해져서 가습

simth999wrld.tistory.com

 

오늘은 SwiftUI의 Property Wrappers를 알아보았습니다. 이걸 모르면 아무것도 못하것죠??

한번 보았던 내용이니 후딱 하고 넘어가겠습니다. 리마인드 하는 마음으로 보자구요

Property Wrapper

반복되는 코드를 간단하게 적용하기 위해 사용되는 문법입니다.

 

 

 

@State

 

@State는 특적 프로퍼티를 뷰의 상태(state)로 만들어줍니다.

무슨소리일까요??

간단하게 변수값이 변경이 되면 자동으로 뷰도 변경이 일어납니다.

 

@State var leftDiceNumber = 1
@State var rightDiceNumber = 1

var body: some View {
    DiceView(n: leftDiceNumber)
    DiceView(n: rightDiceNumber)

    Button {
    self.leftDiceNumber = Int.random(in: 1...6)
    self.rightDiceNumber = Int.random(in: 1...6)

    } label: {
        Text("Roll")
    }
}

 

간단한 코드입니다. VStack등 제끼구 봅시다.

 

leftDiceNumber와 rightDiceNumber는 @State로 선언되어 있습니다.

"Roll"의 버튼이 눌리게 된다면 1~6의 숫자가 랜덤하게 들어가며 주사위의 이미지가 바뀌게 됩니다.

 

만약 @State로 선언되어 있지 않다면 아무리 Roll을 하게되더라도 데이터와 뷰가 바뀌지 않게됩니다.

 

 

 

@Binding

 

@Binding은 다른 인스턴스 소유의 @State 프로퍼티를 가져올때 사용합니다.

struct MyToggleButton: View {
    @Binding var value: Bool

    var body: some View {
        Button(action: {
            self.value.toggle()
        }, label: {
            Text(self.value ? "Hello" : "World")
        })
    }
}

struct ContentView: View {
    @State private var value = false

    var body: some View {
        VStack {
            MyToggleButton(value: $value)
        }
    }
}

위의 코드에서 MyToggleButton의 struct의 value 프로퍼티가 @Binding으로 선언되어있습니다.

이 프로퍼티는 ContentView에서의 뷰가 생성될때 value프로퍼티와 연결되게 됩니다.

 

따라서 두 데이터는 연결되어 한쪽값이 바뀌어도 다른 한 값이 바뀌게 됩니다. 뷰또한 업데이트 됩니다.

 

@State, @Binding은 value타입 즉 값 타입이기에 reference type참조 타입일때는 사용을 하지 못한다는 단점이 있습니다.

참조타입인 클래스에선 사용을 하지 못합니다.

 

 

@ObservedObject

 

@ObservedObject 라는 Property Wrapper를 사용하여 @State, @Binding의 단점을 극복할 수 있습니다.

@ObservableObject를 상속받은 클래스의 프로퍼티는 @ObservedObject 의 프로퍼티 래퍼를 적용하여 뷰와 프로퍼티를 연결시킬수 있습니다.

추적을 원하는 프로퍼티는 @Published의 프로퍼티 래프를 작성해야 합니다.

class MyData: ObservableObject {
    @Published var name = "World"
    @Published var buttonTitle = "Switch to Universe"

    func switchName() {
        if name == "World" {
            name = "Universe"
            buttonTitle = "Switch to World"
        } else {
            name = "World"
            buttonTitle = "Switch to Universe"
        }
    }
}

struct ContentView: View {
    @ObservedObject var data = MyData()

    var body: some View {
        VStack {
            Text("Hello, \(data.name)!")
                .padding()
            Button(
                action: { self.data.switchName() },
                label: { Text(self.data.buttonTitle) }
            )
        }
    }
}

 

 

 

@EnviromoentObject

@EnviromoentObject는 클래스 오브젝트를 추적하기 위한 용도의 프로퍼티 래퍼이다.

ObservableObject를 통해 구현된 타입의 인스턴스를 전역으로 공유하여 사용

앱 전역에 공통으로 사용할 데이터를 주입 및 사용

class SharedData: ObservableObject {
    @Published var configName = "default"
    ...
}

struct ContentView: View {
    @EnvironmentObject var sharedData: SharedData
    ...
}

struct FooView: View {
    @EnvironmentObject var sharedData: SharedData
    ...
}

SharedData를 ObservableObject로 선언후, ContentView와 FooView에서 @EnviromoentObject의 형식으로

참조한다. 이는 여러 곳에서 공유될 만한 데이터를 관리하는 모델로 사용하기 좋다.

 

SharedData를 참조가 시작되기 전에 생성해야한다.

보통은 해당 뷰를 만들기 전에 오브젝트를 생성하고 이것을 enviromentObject()로 알려주어야 한다.

 

var sharedData = SharedData()
...
window.rootViewController =
    UIHostingController(rootView: ContentView().environmentObject(sharedData))

위의 코드가 SharedData 오브젝트를 생성해서 공유를 시작하는 시점이다.

 

SceneDelegate.swift에서 설정.

https://leetaek.tistory.com/67

 

 

 

 

@StateObject (https://pilgwon.github.io/post/state-object-vs-observed-object)

@StateObject는 @ObservedObject와 비슷한 특징을 가졌지만 SwiftUI의 라이프싸이클을 관리하는 

방식에 차이점이 있습니다.

 

뷰에서 ObservableObject 타입의 인스턴스 선언 시 사용할 수 있음.

 

뷰마다 하나의 인스턴스를 생성하며, 뷰가 사라지기 전까지 같은 인스턴스 유지

@ObservableObject의 뷰 렌더링 시 인스턴스 초기화 이슈 해결을 위한 방법

 

매번 인스턴스가 새롭게 생성되는것처럼 외부에서 주입 받는 경우가 아닌 최초 생성 선언 시에 @StateObject를 사용하는 것이 적절한 방법

 

위의 특징이라 저번TIL에 작성을 하였었는데, 흠 너무 추상적으로 적어두어서 다시보니 이해가 가질 않습니다.

 

SwiftUI가 화면을 만들거나 다시 그릴수 있는 가능성이 있다면 인스턴스가 초기화가 되지 않는 @StateObject를 사용한다고

다시 이해를 하였습니다 ^_^

의존 관계로 주입한다면 @ObservedObject

 

생각과 감정

고독합니다.. 고독.... 누군가와 같이 스터디를 하고싶슴다... 프로젝트도 하고싶고... 으악...

앞으로의 계획선언

일단 크리스마스를 즐겨보자구요 ^_^

 

 

 

 

 

(보면서 공부했슴다.. 감삼다!)

https://seorenn.github.io/note/swiftui-property-wrappers.html

 

SwiftUI Property Wrappers - Seorenn Note

@State 는 특정 프로퍼티를 뷰의 상태(state)로 만들어준다. 즉 이 프로퍼티가 변경되면 자동으로 뷰의 데이터도 변경되고, 뷰의 데이터를 바꿔도 이 프로퍼티의 데이터도 자동으로 변경된다. struct

seorenn.github.io

 

'TIL' 카테고리의 다른 글

TIL_20240103  (0) 2024.01.05
TIL_20231226  (0) 2023.12.26
TIL_20231221  (0) 2023.12.21
TIL_20231212  (0) 2023.12.12
TIL_20231126  (0) 2023.11.26

흐아.. 아무것도 하기 싫지만 일단 의자에 앉았으니 뭐라도 해야겠죠..?

ㅋㅋㅌ 그동안 uikit만 공부를 했지만,, 패캠에서 산 강의는 SwiftUI이기에,, 기초를 다듬으러

다시 안젤라의 강의를보며 SwiftUI의 기초를 다듬어 보겠~~~~~~~습니다~~

 

 

배운점

preViewDevice

#Preview {
    ContentView().previewDevice(PreviewDevice(rawValue: "iPhone SE"))
}

프리뷰에 디바이스를 다른것으로 확인 하기 위해선 위와 같은 코드로 설정을 하여 확인을 한다.

 

xcrun simctl list devicetypes

위의 코드를 터미널에 입력하면 rawValue에 들어갈 수 있는 장치를 나열하여 알려줍니다 ^_^

 

iPhone 6s (com.apple.CoreSimulator.SimDeviceType.iPhone-6s)

iPhone 6s Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus)

iPhone SE (1st generation) (com.apple.CoreSimulator.SimDeviceType.iPhone-SE)

iPhone 7 (com.apple.CoreSimulator.SimDeviceType.iPhone-7)

iPhone 7 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus)

iPhone 8 (com.apple.CoreSimulator.SimDeviceType.iPhone-8)

iPhone 8 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-8-Plus)

iPhone X (com.apple.CoreSimulator.SimDeviceType.iPhone-X)......

(아이폰 뿐아닌 패드, 워치, 티비등의 장치를 알려줍니다.)


⌘ + ctrl + L 을하여 오브젝트 라이브러리를 확인할 수 있습니다.

(각 오브젝트의 modifier들 또한 확인할 수 있습니다.)

 

 

modifier는 메서드의 아랫줄의 개행을 하여 작성한다. (가독성을 위해)

struct ContentView: View {
    var body: some View {
        ZStack {
            Color(.lightGray)
                .edgesIgnoringSafeArea(.all)
            VStack {
                Text("I AM Rich")
                    .font(.system(size: 40))
                    .fontWeight(.bold)
                    .foregroundColor(Color.white)
                                
                Image("diamond")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 200, height: 200, alignment: .center)
            }//HStack
        }//ZStack
        .padding()
    }
}

 

 

 

구글 fonts를 사용해서 기본 글씨체에서 벗어나 봅시다 ^_^
https://fonts.google.com/

 

Browse Fonts - Google Fonts

Making the web more beautiful, fast, and open through great typography

fonts.google.com

 

 

저는 Pacifico라는 글꼴을 다운로드 받아서

Fonts 파일에 넣어줬어요 ^_^

 

 

 

 

 

어지러운 글씨체인걸요..?

 

 

 

 

(커스텀 글꼴 설정)

 

글씨체 파일을 추가할때 빌드타겟을 꼭 체크 해줘야 합니다 ^_^

 

 

Text

Text("Chex")
    .font(.custom("Pacifico-Regular", size: 40))
    .bold()
    .foregroundColor(.white)

"Chex"의 텍스트를 추가하고, bold체를 추가, 글씨색인 foregroundColor는 하얀색으로 설정 하였습니다.

uiki의 Label과 비슷한것으로 보입니다.

 

Image

Image("기모즈")
    .resizable()
    .aspectRatio(contentMode: .fit)
    .frame(width: 200, height: 200)
    .clipShape(Circle())
    .overlay(Circle().stroke(Color.white, lineWidth:  5))

간단한 Image를 넣고, 원의 형태와 테두리를 설정한 모습입니다.

 

이미지의 사이즈를 조절하기 위해 resizable을 선언합니다, aspectRatio로 .fit의 사이즈로 이미지를 채웁니다. 

너비와 높이는 200을 하면 원의 이미지가 추가됩니다.

 

이후 테두리 설정을 위해 뷰의 모양을 바꾸어주는 clipShape를 Circle로 선언합니다.

overlay는 뷰 원본의 공간을 기준으로 그 위에 새로운 뷰를 중첩하기 위한 수식어 입니다.

stroke를 이용해 굵기 5인 하얀 테두리를 설정합니다.

 

이 테두리를 설정하기 위해 검색을 하던중, 2가지의 방법이 있더군요.

바로 border과 stroke입니다.

 

border는 View타입의 속성이며 선을 그릴때 뷰의 바깥부터 그려준다고 합니다.

stroke는 Shape타입의 속성이며 선을 그릴때 뷰의 안쪽부터 그려준다고 합니다.

https://nsios.tistory.com/178

 

 

오즈를 보여주는 귀여운 화면을 그렸습니다..

 

 

 

 

 

 

 

 

 

 

 

 

 

 

생각과 감정

요즈음 다시 개발 이놈이랑 권태기가 오는것 같습니다... 강의로 조금 화해를 해보려 합니다.

uikit만 공부하다 Swiftui를 공부하니 흥미가 오르는 기분아닌 기분! 기분전환을 해봤습니다..

완강하고 간단한 개인앱 하나 만들어봐야겠군요~_~

 

앞으로의 계획선언

나태해지지만 않으면 앞으로의 계획은 성공이다..

 

'TIL' 카테고리의 다른 글

TIL_20231226  (0) 2023.12.26
TIL_20231223  (0) 2023.12.23
TIL_20231212  (0) 2023.12.12
TIL_20231126  (0) 2023.11.26
TIL_20231120  (0) 2023.11.20

+ Recent posts