iOS swapAt 함수 사용해보기

|

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


swap

배열에서 서로 값을 바꿔야 하는 상황에 사용

var arr = [9,8,7,6,5,4,3,2,1]
swap(&arr[0], &arr[1])

그런데 이와 같은 방법이 swift4에서 변동사항이 생겼다고 한다.

Overlapping accesses to ‘arr’, but modification requires exclusive access; ….

즉, swift4 이후부터는 컬렉션에 있는것들을 스왑하려고 하면 위와 같은 에러가 발생한다.
그 이유는 스왑이 Law of Exclusivity 를 위반하기 떄문이다.

Law of Exclusivity

변수가 동시에 충돌하는 방식으로 엑세스 하지 못하게 하는 것

If a storage reference expression evaluates to a storage reference that is implemented by a variable, then the formal access duration of that access may not overlap the formal access duration of any other access to the same variable unless both accesses are reads.

스토리지 참조 표현식(storage reference expression)이 변수에 의해 구현되는 스토리지 참조에 대해 평가(evaluates)하는 경우, 해당 접근(access)의 공식 접근 기간이 두개의 접근이 모두 읽히지 않은 한, 동일한 변수에 대한 접근 기간과 겹칠 수 없다.

즉, 접근은 공식적인 전체 접근 시간동안 독점적이어야 한다는 것 이다.

하지만 스왑의 목적은 mutable collection 내에서 두 요소를 교체하는 것이다. 하지만 소유숸 선언의 일부로 제한된 변경사항들에 따르면 이제 이것은 더이상 유효한 것이 아니다. 단일 변수는 동일한 함수에 대해 서로 다른 두개의 인수로 전달될 수 없다.

swapAt

var arr = [1,2,3]
arr.swapAt(1,2)  // [1,3,2]

즉, 요소 자체를 넘겨주지 않고 인덱스를 넘겨준다.

iOS Configuring the Event-Related Behavior > isUserInteractionEnabled, isMultipleTouchEnabled, isExclusiveTouch

|

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


기존 코드에 isUserInteractionEnabled가 사용되는것을 보곤 이게 뭐지? 하고
UIView의 도큐먼트를 살펴보게 되었습니당. Configuring the Event-Related Behavior라고 하면서
3개의 프로퍼티가 있는것을 보게 되었다..

isUserInteractionEnabled

유저의 이벤트가 event queue로부터 무시되고 삭제됐는지를 판단하는 boolean 값

만약 isUserInteractionEnabled == false를 하면 view를 위한 touch, press, keyboard 그리고 focus event는 event queue에서 무시되고 삭제된다. 반대로 isUserInteractionEnabled == true를 하게 된다면 event는 정상적으로 뷰에 전달이 된다. default는 true이다.

그런데 이를 사용할때에도 예외는 있나보다.

애니메이션을 적용하는 동안에는 이 프로퍼티의 값이 false든 true든 상관없이 user interaction은 disable된다고 한다.
애니메이션이 일어나는 뷰를 포함해서 말이다. 이를 막고싶다면 애니메이션 옵션으로 allowUserInteraction을 주면 된다고 한다.

isMultipleTouchEnabled

뷰가 한번에 2개 이상의 터치를 수신하는지 여부를 나타내는 boolean 값

만약 isMultipleTouchEnabled == true를 설정하면 multi-touch sequence 와 관련된 모든 터치를 받고 뷰의 bounds에서 시작한다. 반면 isMultipleTouchEnabled == false를 설정하면 오직 multi-touch sequence 안에 있는 first touch event만 받는다고 한다. default는 false라고 한다.

알아둬야 할 점은 이 프로퍼티는 gesture recognizer에 영향을 끼치지 않는다는 점이다.
gesture recognizer는 view에서 일어나는 모든 터치를 수신한다.

그리고 이 프로퍼티가 false로 설정되어있다고 할때, 같은 윈도우 안에있는 다른 뷰들은 여전히 터치 이벤트를 받을 수 있다는 특징이 잇다. 이런때에 multi-touch event를 서로 배타적으로 다루고 싶다면, isExclusiveTouch프로퍼티와 isMultipleTouchEnabled 프로퍼티를 둘다 true로 설정하면 된다고 한다.

isExclusiveTouch

리시버가 터치이벤트를 exclusively하게 다룰지를 나타내는 boolean 값

만약 isExclusiveTouch == true로 설정하면 동일한 윈도우의 다른 뷰에 대한 터치이벤트를 차단한다. 반면 isExclusiveTouch == false를 한다면 차단하지 않는다. default는 false 값이다.

동일한 윈도우안에서 어떤 뷰가 터치이벤트를 전달하면 다른 뷰에 대한 터치이벤트는 차단시키는 것이다.

동일한 윈도우에서 서로 다른 뷰의 터치 이벤트 등을 처리할때 서로 관계없이 작업이 진행되게 하기 위해서 단순히 isExclusiveTouch == true를 하면 되는것같아 보이지만 문서에서는 이 뿐만 아니라 isMultipleTouchEnabled == true까지 진행해줘야 한다고 적혀있다.

iOS replacingOccurrences 사용해보기

|

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


replacingOccurrences

앱을 개발하다보면 문자열에서 특정 문자열을 제거 / 변경하여 사용해야하는 경우가 있다.
이때 사용하는 메소드가 replacingOccurrences이다.

import Foundation

let string = "안-녕하세요"
string.replacingOccurrences(of: "-", with: "")

이렇게 사용하는것의 의미는 아래와 같다.
string안에 들어간 “-“를 ““로 바꾸어 새로운 문자열로 반환해 달라.

func replacingOccurrences(of target: String, with replacement: String) -> String

즉, target 파라미터에 바꾸고 싶은 문자열을 전달하고, replacement 파라미터에 바꿀 문자열을 전달해주면 된다.

예제는 또 아래와 같다.

func hideName(myName: String) -> String {
    let secontIndex = myName[myName.index(after: myName.startIndex)]
    return myName.replacingOccurrences(of: String(secontIndex), with: "*")
}

hideName(myName: "홍길동")
// return : "홍*동"

단 한가지 이를 사용해서 아쉬운 점은 첫번째 예시에서 처럼 만약에 바꾸려는 상수 string이 안-녕-하세요라고 해보자.
나는 첫번째 -만 대치해서 바꾸고 싶은건데 replacingOccurrences를 사용하게 되면 모든 -가 다 변경되고 만다.

이런때에는 replacingOccurrences이 아닌 다른 방법을 사용하는것이 좋다.
이때의 이런때는 내가 명확하게 없애고 싶은 문자열이 딱 존재할때를 의미한다.

func hideName(myName: String) -> String {
    var myName = myName.map { String($0) }
    myName[1] = "*"
    return myName.joined()
}

hideName(myName: "베르나르 베르베르")
// return : "베*르나르 베르베르"

iOS prepareForReuse 란?

|

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


prepareForReuse

테이블 뷰를 사용할때 보통 셀을 재사용하는 경우가 대부분일 것이다.
셀을 말그대로 재사용하기 때문에 재사용된 셀에서 보여주지 않아야 하는 텍스트 혹은 버튼 등이 보여지는 경우가 있다.

말 그대로 재사용했기 때문이다.

예로 들어 생각해보자.

테이블 뷰가 있고 해당 화면에서는 하나의 재사용 셀들이 주르륵 있다.
현재 보여지는 화면으로부터 스크롤을 해서 아래의 셀들이 보여지고 그 셀들 또한 모두 재사용이 되고 있다.
셀은 재사용이 되었지만, 셀 안에 들어가는 데이터의 조건은 각각 다를 수 있다.
그러나 셀은 재사용이 되었기 때문에 원치 않는 정보가 들어가질 수 있다.

셀 그 자체는 안의 데이터가 어떤것이라는것과는 무관하게
셀 안에 레이블이 들어간다면 그 레이블을 띄워주는 그 자체의 행위만 하기 때문이다.

그렇기 때문에 이렇듯 재사용 셀을 사용할 때는 반드시 모든 값이 초기화 되어져야 한다.
그리고 이렇게 초기화를 하기 위해 호출하는 함수가 prepareForReuse이다.

Snapkit에서 labeled란?

|

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


labeled

코드로든 스토리보드로든 이를 통해 레이아웃을 짤때 레이아웃이 맞지 않아 콘솔에 오류가 생기는 경우가 있다.

이미지의 주소라던지 각 객체의 주소가 0x000ff280 이런식으로 나와있기 때문에 이게 어떤 객체를 말하는건지 파악이 안되는 경우가 많다. 이런때에 보통 breakpoint를 잡거나 레이아웃 에러를 잡아주는 사이트?를 들어가서 파악을 할 수도 있지만 스냅킷에서는 좀 더 편리한 방법이 잇다.

그게 바로 labeled 기능이다.

titleLbl.snp.makeConstraint { make in
  make.width.equalToSuperView().multipliedBy(0.45).labeled("titleLbl")
}

이런식으로 labeled를 달아주면 이후에 콘솔창에 뭐가 문제인지 확인하기 편하진다.
각 객체에 이름을 달아준다고 생각하면 쉬울 것 같다!