[231204] Today I Learned

YoungHyun Kim·2023년 12월 4일
1

TIL ✍️

목록 보기
10/68

프로퍼티 옵저버

프로퍼티를 관찰하면서 변경 사항이 발생할 때 실행.
실행 순서 : willSet > didSet
저장 프로퍼티연산 프로퍼티에 추가할 수 있음

didSet, willSet

didSet

  • 새 값이 저장된 직후에 호출, 이전 프로퍼티의 값이 oldValue라는 이름으로 제공됨.

willSet

  • 값이 저장되기 직전에 호출, 새로운 프로퍼티의 값이 newValue라는 이름으로 제공됨.
class UserAccount {
    var username: String
    var password: String
    var loginAttempts: Int = 0 {
        didSet {
            if loginAttempts >= 3 {
                print("로그인 시도가 3회 이상 실패하였습니다. 계정이 잠겼습니다.")
                lockAccount()
            }
        }
    }
    
    var isLocked: Bool = false {
        didSet {
            if isLocked {
                print("계정이 잠겼습니다.")
            } else {
                print("계정이 잠금 해제되었습니다.")
            }
        }
    }
    
    init(username: String, password: String) {
        self.username = username
        self.password = password
    }
    
    func login(with enteredPassword: String) {
        if enteredPassword == password {
            print("로그인 성공!")
            loginAttempts = 0 // 로그인 성공 시 로그인 시도 횟수 초기화
        } else {
            print("잘못된 비밀번호입니다.")
            loginAttempts += 1 // 로그인 실패 시 로그인 시도 횟수 증가
        }
    }
    
    private func lockAccount() {
        isLocked = true
    }
    
    func unlockAccount() {
        isLocked = false
    }
}

// 사용자 계정 생성
let user = UserAccount(username: "user123", password: "password123")

// 로그인 시도
user.login(with: "wrongpassword") 
// 출력:
// 잘못된 비밀번호입니다.
// loginAttempts == 1

user.login(with: "wrongpassword") 
// 출력:
// 잘못된 비밀번호입니다.
// loginAttempts == 2

user.login(with: "wrongpassword") 
// 출력:
// 잘못된 비밀번호입니다.
// loginAttempts == 3
// 로그인 시도가 3회 이상 실패하였습니다. 계정이 잠겼습니다.
// 계정이 잠겼습니다.

// 계정 잠금 해제
user.unlockAccount() // 계정이 잠금 해제되었습니다.

타입 캐스팅

변수나 객체의 타입을 다른 타입으로 변환하는 프로세스

is

lhs is rhs의 결과를 bool타입으로 반환함

let char: Character = "A"
 
print(char is Character) // true
print(char is String)   // false
 
let bool: Bool = true

print(bool is Bool) // true
print(bool is Character) // false

as, as!, as?

업 캐스팅 : as (하위 클래스 ➡️ 상위 클래스)
다운 캐스팅 : as? , as! (상위 클래스 ➡️ 하위 클래스)

as

  • 컴파일 단계에서 캐스팅이 실행, 즉 타입 캐스팅이 성공할 경우에만 사용할 수 있음.
  • 캐스팅 실패 시 에러가 발생
  • 캐스팅하려는 타입이 같은 타입이거나 부모클래스 타입이란 것을 알 때 as연산자를 사용

as?

  • 런타입에 캐스팅이 실행, 성공하면 옵셔널 타입의 인스턴스를 반환, 실패 시 nil을 반환
  • 실패할 가능성이 있을 때, as?를 사용

as!

  • 런타임에 특정 타입으로 강제 캐스팅, 실패 시 런타임 에러 발생 가능
  • 캐스팅 성공 시 인스턴스(옵셔널X)를 반환

접근제한자

코드 요소에 대한 외부 접근을 제한 ➡️ 모듈 간의 접근성과 보안을 조절

접근제한자

다른 소스 파일이나 모듈의 코드에서 코드 일부에 대한 접근을 제한함
[제약 적음] open < public < internal < fileprivate < private[제약 많음]

  • open : 모든 소스 파일에서 해당 level에 접근 가능 + 모든 곳에서 서브클래싱 가능
  • public : 모든 소스 파일에서 해당 level에 접근 가능 + 같은 모듈 내에서만 서브클래싱 가능
  • internal : 같은 모듈 내에서만 접근 가능 (default)
  • fileprivate : 같은 소스 파일 내에서만 접근 가능
  • private : 클래스 내부에서만 접근 가능

[프로그래머스] 바탕화면 정리

  • 저번 주에 말했었던 강제 옵셔널 해제 대신, 옵셔널 바인딩을 사용해서 문제를 해결했다. 기분이 참 좋다.

github, git

~~.xcuserstate 파일 충돌 문제 해결

  1. Xcode에서 코드를 보다가 브랜치를 바꿔타려니 해당 에러가 발생해서 add, commit 후에나 switch가 되는 현상이 있었다.
  2. 곰곰히 생각해봐도 그냥 프로젝트를 열고 수정한 것이 없는데 왜 에러가 뜨는지, 이런 에러가 계속되면 굉장히 불편해질 것 같아(나 뿐만 아니라 팀원들까지) 오류가 뜨지 않도록 하는 해결법을 찾았다.
  3. 방법은 이렇다
  • 터미널에서 해당 충돌이 난 프로젝트의 디렉토리로 이동한다.
git rm --cached ~~.xcuserstate
git commit -m ' Removed file that shouldnt be tracked'
  • 위의 명령어 실행 후 터미널에서 .gitignore 파일을 만든다.
  • *.xcuserstate 구문을 입력한 후 저장한다.
  • 작업중인 브랜치에서 순서대로 add, commit, push 해주면 문제가 해결된다.
  1. 해결하고 나서 보니, 협업을 위한 프로젝트에서는 해당 작업을 선조치하는 것이 많은(?) 팀원들이 고생하지 않는 방법이라는 생각이 들었다.
  2. 찾다보니 프로젝트 시작 시에, 사용하는 기술스택에 따라서 추천되는 .gitignore 파일을 생성해주는 사이트가 있었다. 아래에 링크를 첨부하고, 나도 자주 사용하도록 해봐야겠다.

https://www.toptal.com/developers/gitignore

profile
iOS 개발자가 되고 싶어요

0개의 댓글