전체 뷰 사이즈를 찍어보면

print(self.view.frame.size) // (320.0, 568.0)

 

로 매우 아담한 사이즈가 찍힌다.

 

이 뷰에 텍스트뷰를 하나 넣었는데

텍스트를 넣으면서 해당 화면을 넘어가지않고( 스크롤이 생기기전까지) 컨텐츠를 채워넣으려고하고있다.

해서

textView.contentSize.height 를 

textView.frame.height 를 보면서 계속 넘어가는지 확인하면서 텍스트를 넣었으나

 

이상하게 페이지가 엄청나게 많이 넘어간다

한 두줄 넘어가는 경우면 뭔가 조건문 순서가 잘못됐구나 하는데

넘어가도 너무나 넘어간다

 

해서 

textView.frame.size 를 찍어보면...

(398.0, 772.0) ...

실 뷰의 높이가 568인데 오토레이아웃으로 양옆 위아래 여백넣은 텍스트뷰가 700백이 넘어간다.

 

도대체 왜이러는지 몰라 답답한 상황이라

나중에라도 누군가에게 물어보고싶어 이글을 남긴다.

 

 

추가- 21.04.18 00:34

해당 사이즈는 스토리보드에서 사용하고있는 화면의 크기로 보임.

기존

viewWillAppear 에서 

 

viewDidAppear로 변경하니 정상적으로 크기가 나옴.

 

스토리보드 사용시

스토리보드로 먼저 구성되고 

후에 코드로 나온다고한다.

라이프사이클에서 어느부분이 돌아가는지 복습을 해보자 

 

 

 

이번 rn으로된 프로젝트에 ios용 타겟추가해주는 팀에서 일하는중 

rn앱을 시뮬로 돌리려면 항상 어디선가 문제가 발생하고 고치느랴 오전 ~ 점심시간이 다 날라갔다.

이번에도 역시 안되다가 모든 pod파일과 빌드파일들을 삭제하고 이참에 업데이트 까지 해놨더니

이번엔 이상한 오류가 발생

event2/event-config.h  file not found 라며 안된다. 

찾아보니 이는 flipper 라는 묘한녀석의 버전이 안맞아 생기는 문제라고하는데....

cocoapods의 버전을 업데이트한게 문제가 된것으로 보인다.

 

당연히 자동으로 버전관리를 하기에 버전의 번호가 안적힌상태였는데 

이를 아래와같이 변경해주면 무사히 빌드가 됐다.

 

Podfile 중

 

use_flipper!

use_flipper!({ 'Flipper-Folly' => '2.3.0' })

 

항상 도움을 주는 스택오버플로우 여러분께 감사인사를 드린다.

stackoverflow.com/questions/66019068/event2-event-config-h-file-not-found

 

'event2/event-config.h' file not found

I am trying to build a react-native app in iOS but unfortunately coming across the following issue (referring to libevent/Flipper): 'event2/event-config.h' file not found I have react-native v0.63....

stackoverflow.com

 

뭔가 거품이 올라와서 차오르는 버튼이 적용된 디자인을 받아 적용해달라고 했다

머릿속 기억에서는 그냥 거품 네개가 순서대로 뽀글뽀글 올라와서 색을 채우는 단순한 디자인이라 바로 Ok했는데

막상 만들고 디자인 예시 보내온거랑 비교해보니 확연히 다르다

뭐 아무튼 그래서 디자인을 변경해보고자 예시용 프로젝트를 만들어서 돌리는데

뭔 설치를 못한다느니 어쩐다느니 검색해보면 빌드파일 삭제하고 시뮬레이터 재시동하면 된다는데 난 전혀 안된다.

 

설명을 잘 읽어보니 제목과 같은 오류가 나고있다.

 

아니 이게 무슨 말인가 나는 cocoapod로 자동관리를 하는데 ;;;

 

Pods프로젝트 파일을 열어보니 진짜 SnapKit의 Info.Plist가 잡혀있지않는다.

 

Pod를 재설치하면 되겠거늘 하고 재설치를 해봤으나 여전히 해당 파일은 다운로드가 되지않는다.

 

인간성을 땅에 내려놓고 유튜브 영상이나 보면서 마인드 수치를 채우니 다른 프로젝트에서 해당 파일을 복사하자 라는 생각이 들어 

 

파일내용자체를 남겨두려고 이글을 쓴다

 

원래는 아래 사진과 같이

하단 SnapKit폴더의 Support Files에 SnapKit-Info파일이 있어야한다.

 

재설치해도 해당 파일이 생성안된다면 그냥.... 이렇게 생성해주자 

 

원래 있어야하는 위치에 New File을 눌러주고

 

Preperty List 로 하나 생성해준다 

 

 

이름은 SnapKit-Info.plist로 지정해주고 타겟은 둘다 선택해준다. 

 

생성됐으면 해당 파일을 Source Code모드로 열어준다.

 

 

아래 내용을 복붙 저장

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleExecutable</key>
  <string>${EXECUTABLE_NAME}</string>
  <key>CFBundleIdentifier</key>
  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>${PRODUCT_NAME}</string>
  <key>CFBundlePackageType</key>
  <string>FMWK</string>
  <key>CFBundleShortVersionString</key>
  <string>5.0.1</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleVersion</key>
  <string>${CURRENT_PROJECT_VERSION}</string>
  <key>NSPrincipalClass</key>
  <string></string>
</dict>
</plist>

 

 

Pods의 프로젝트 파일을 xcode상에서 열어보면 SnapKit 의 Info 파일이 선택되지 않았다고 아래와 같이 뜬다.

Choose Info.plist File... 을 눌러주자

 

 

위에서 생성한  파일을 선택 해준다,.

 

선택하고 다른 타깃을 보고 오거나 하면 아래와같이 다시 잘 보인다,

 

 

마지막으로 잘됐는지 빌드해본다.

 

잘된다.. 만세

    guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
    extensionContext?.open(url, completionHandler: { (success) in
      if !success {
        var responder = self as UIResponder?
        while (responder != nil){
          let selectorOpenURL = NSSelectorFromString("openURL:")
          if responder?.responds(to: selectorOpenURL) == true {
            _ = responder?.perform(selectorOpenURL, with: url)
          }
          responder = responder?.next
        }
      }
    })

 

열기 실패시에 대한 내용에 대해 자세히 알고싶어져 저장

나중에 찾아보자.

비교 연산자는 결과값이 False or True로 나오는 연산자이다.

 

좌항과 우항을 비교하여 Bool형 값을 반환하는 연산자이다.

기호는 

==

!=

>

<

>=

<=

를 사용한다.

 

 

1.  == 와 != ( 같으면, 다르면)

 

a1과 b1가 각각 5와 4일경우

let a1 = 5

let b1 = 4

 

두 상수를 비교하면 

let a = a1 == b1

let b = a1 != b1 

 

같이 표현하며

a의 값은 false 가 되며 b는 true가 된다.

 

이렇게 변수에 저장하는것 보단 후에 나올 흐름제어, 조건문에서 같이 많이 사용하게 될것이다.

 

위의 예제처럼

== 는 우항과 좌항이 같을 경우 true, 아니면 false를 반환한다.

!= 는 우항과 좌항이  다를 경우 true를 아니면 false를 반환한다.

 

3. > 와 < (크다면, 작다면)

 

위의 a1,b1을 재활용해서 비교해보자

a1 > b1의 값은 true이다. > 는 좌항이 우항보다 클 경우 true를 반환한다.

a1 < b1의 값은 false이다. < 는 우항이 좌항보다 클 경우 true를 반환한다.

 

4. >= 와 <= (이상, 이하)

let a2 = 5

let b2 = 10

let c1 = 5

 

일경우 

let g = a2 >= b2 // false

let h = a2 <= b2 // true

let i = a2 >= c1 // true

 

위에서 부터 

a2 가 b2보다 크거나 같은가

a2 가 b2 보다 작거나 같은가

a2 가 c1 보다 크거나 같은가 

이다.

 

 

5. Equatable

모든 값이 비교연산자가 사용가능한것이 아니다.

비교 연산자가 사용 할 수 있는 형식은 Equatable의 규칙을 따르는 데이터형만이 가능하다.

스위프트에서는 프로토콜 이라는 규칙들이 있다. 이는 사용자가 정의할 수 있고 언어에서 미리 정의해둔 규칙이다.

그런 여러 프로토콜중에 Equatable이라는 규칙이 있고 이는 좌항과 우항이 비교할때 어떤식으로 비교가 될것인가를 규정해둔 규칙이다.

이 스위프트 기본이라는 글들을 언제까지 쓰게 될지 모르겠지만 프로토콜까지 쓰게 된다면 상당히 훗날의 일이 될것이다.

이번엔 산술연산자1에 이어서 곱셈과 나눗셈을 한다.

 

1. 곱셈

곱셈은 * 를 기호로 사용한다 x가아니다.

(이전편에서부터 그러하였으나 // 는 주석이다. 앞으로 print문의 출력은 되도록 주석을 통해 적도록 하겠다.)

 

let result = 3 * 5 

print(result) // 15

 

별 다를바 없는 평범한 곱셈이다.

 

이전편의 타입을 생각해서 하자면 

두 곱은 항상 같은 타입끼리만 가능하다. ( 다른 사칙연산도 마찬가지다 )

 

데이터 타입에 대해 이야기할때 다루지 않았지만 각 타입의 변수는 저장가능한 범위가 있다.

float는 타입에 대해 이야기할때 실수인 double보다 작은 범위의 실수를 가지는 타입이다. 해당 타입의 범위가 넘어가면 제대로된 값이 담아지지않는다.

큰 수를 다루게 된다면 항상 타입의 범위에대해 생각해두자.

 

해당 범위는 이글에서 다루지 않겠다.

 

 

 

2. 나눗셈

나눗셈은 / 를 기호로 사용한다 ÷ 가 아니다.

/도 사실 타입에 따라 좀 다른식으로 계산이 된다

만약 정수형 타입의 두 수를 나눗셈을 시도했다면( ex : let b = 6 / 4 )

해당 결과는 몫만이 들어가게된다.(b는 1)

 

만약 위의 나눗셈 예제에서 몫을 제외한 나머지를 구하고싶으면 기호 % 를 사용하면된다 

ex: let c = 6 % 4 // 2

 

정수형이 아닌 실수형끼리 나눗셈을 하면 원래 나눗셈의 원하는 결과처럼 소수점까지 잘 나오게된다.

ex: let d = 6.0 / 4.0 // 1.5

 

나눗셈에서 주의할 점은 0으로 나눠서는 안된다.

예시들 처럼 숫자로 바로 표현되어서 0으로 나눠지려고 할때 눈으로 바로 알 수 있지만 

변수 끼리 나눗셈을 하게될 경우가 왕왕 생기기에 필요시 나누는 수에 대한 체크는 꼭 해야할것이다.  해당 부분은 나중에 다룰 예정이다.

 

 

3. 사칙연산 축약 

사칙 연산이 끝났다.

해당 사항을 이용해서 짧게 쓰는 축약에 대해 이야기 하려한다

swift의 문서에서는 지금 쓰려고 하는 기호를 Compund Assignment Operator라고 부른다.

복합 할당 연산자라고 부르는데

 

아래와 같다

 

두 정수 e와 t를 정의하고 

var e = 5

let t = 5 

 

e에 다가 t의 값을 더한 값을 다시 변수e에 넣으려고할때 

기존이라면 아래와 같다.

 e = e + t // 10

이런식으로 하면 우선 등식의 우측란이 먼저 계산되고 

좌측란의 e에 할당 연사자인 = 를 통해 e에 할당된다.

 

e = e + t 를 축약해보자면  e += t 와 같이 쓸 수 있다.

 

+= 는 좌측의 변수에 우측 값을 더한 값을 저장한다.

-= 는 좌측의 변수에 우측값을 빼한 값을 저장한다.

*= 는 좌측의 변수에 우측값을 곱한 값을 저장한다.

/= 는 좌측의 변수에 우측값을 나눈 값을 저장한다.

 

ex)

e와 t를 각각 5로 정의한다. e는 변수로(var) t는 상수로(변하지 않는 수 let)

var e = 5

let t = 5 

 

위에서 부터 아래로 순서대로 계산이 진행된다면 

e += t // 5 + 5 = 10

e -= t // 10 - 5 = 5

e *= t // 5 * 5 = 25

e /= t // 25 / 5 = 5

 

print(e) // 5 

 

산술 연산자는 여기서 마무리 짓고 덤으로 적은 복합 할당 연산자도 끝이나 

다음은 비교 연산자를 다루겠다.

 

 

 

 

 

 

 

 

 

  enum Vibration {
        case error
        case success
        case warning
        case light
        case medium
        case heavy
        @available(iOS 13.0, *)
        case soft
        @available(iOS 13.0, *)
        case rigid
        case selection
        case oldSchool

        public func vibrate() {
            switch self {
            case .error:
                UINotificationFeedbackGenerator().notificationOccurred(.error)
            case .success:
                UINotificationFeedbackGenerator().notificationOccurred(.success)
            case .warning:
                UINotificationFeedbackGenerator().notificationOccurred(.warning)
            case .light:
                UIImpactFeedbackGenerator(style: .light).impactOccurred()
            case .medium:
                UIImpactFeedbackGenerator(style: .medium).impactOccurred()
            case .heavy:
                UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
            case .soft:
                if #available(iOS 13.0, *) {
                    UIImpactFeedbackGenerator(style: .soft).impactOccurred()
                }
            case .rigid:
                if #available(iOS 13.0, *) {
                    UIImpactFeedbackGenerator(style: .rigid).impactOccurred()
                }
            case .selection:
                UISelectionFeedbackGenerator().selectionChanged()
            case .oldSchool:
                AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
            }
        }
    }

stackoverflow.com/questions/26455880/how-to-make-iphone-vibrate-using-swift/57162220

 

How to make iPhone vibrate using Swift?

I need to make the iPhone vibrate, but I don't know how to do that in Swift. I know that in Objective-C, you just write: import AudioToolbox AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); But

stackoverflow.com

 

1에 비해 2가 짧고 2에 비해 이번 3은 더 짧을것이다.

예전에 받은 SwiftUI책을 이제서야 좀 보고있는데

이 책이 한 반절은 스위프트 언어에 대해 다룬다.

그 내용을 보고 있자니 내가 얼마나 답답하게 진행했는지 생각되어 해당 부분들을 짧게짧게 할 생각이다.

스위프트 공식 홈페이지의 기본서가 왜 그리 짧게되어 있는지 이제야 좀 알겠다. 

 

 

이번은 1에서 다뤘어야할 데이터형에 대해서 적을것이다.

실제 있는 데이터형은 무척이나 많으나 여기서는 몇가지만 적을것이고 

원래는 2번에 이어 곱셈과 나눗셈을 다뤄야하나 곱셈 나눗셈을 하기전에 데이터형을 짚고 넘어가야할듯 하여 집어 넣었다.

 

 

해당 내용에는 Int8 ,16, 32 와 같이 나뉘는 애들은 생략하겠다.

 

1. 정수

우선 기본적으로 숫자를 나타내는 정수인 Int가 있다 

1편에서 값을 저장할때는

 

공간의 형식(let / var) 공간의 이름 = 값 

 

이라고 했는데 사실 하나더 있다

 

형식 이름:데이터타입 = 값 

 

실제로는 이렇다.

 

스위프트에서는 값을 보고 이 애가 사실 타입이 무엇이겠구나 라며 추정해주며 해당 타입을 자동으로 지정해주기에 데이터타입을 적지 않았었다.

 

이 정수에서는 위의 나눗셈할때 적은 설명 그대로 정수인 몫만 구하고 나머지는 %로 구한다.

 

ex) let a:Int = 4

 

2. 실수

여기서 말하는 실수는 단순히 소수점이 포함된 수이다.

이 실수에는 타입이 두가지가 있는데

Float 형과 Double형이다.

해당내역은 값을 저장하는 범위와 상관이 있으나 일단 Double로 기억하고 나중에가서 생각하자.

 

ex) let b:Double = 0.1

 

3. 문자열

1편에서부터 사용한 문장의 형식이고 String으로 적는다.

 

ex) let c:String = "Hello world"

 

4. 문자

문장이 아닌 단 하나의 글자만을 이용할때 필요하다. Char라고 적는다

ex) let d:Character = "a"

 

String이 제공하는 함수와

Character가 제공하는 함수가 다르기에 필요에 따라 다르게 쓰인다

무조건 글자하나만이라고 해서 Character를 사용할 필요가 없다.

 

5. 논리형

스위프트에서는 참과 거짓을 저장하는 타입이 따로있다.

Bool 로 적는다

 

let e:Bool = false

let f:Bool = true

 

 

6. 배열

배열은 같은형식의 여러값을 한번에 묶어놓을때 사용한다

타입은 Array<값하나의 형식> 또는 [값하나의 형식] 라고 적는다

 

1,3,5,7 이라는 수들을

let ab:Array<Int> = [1,3,5,7]

이라고 적을 수 있고

let ab:[Int] = [1,3,5,7] 로 적을 수 있다.

 

 

해당 수들을 사용하고 싶다면

ab[0]

ab[1] 이런식으로 뒤에 번호를 붙여 사용한다.

배열은 가장 앞에 있는 자리를 0번으로 부른다.

 

print(ab[0]) 

라고 하면 1이 출력된다.

 

 

7. 튜플

6의 배열은 같은 형식의 값만 묶었다면

튜플은 여러가지 값을 묶을 수 있다.

그냥 괄호로 묶으면된다

Int형숫자 4 와 Double형 숫자 3.141592 와 String형 문자열 "abcdefg"를 묶으면

let abc = (4, 3.141592, "abcdefg")

접근은 앞에서부터 0으로

숫자4를 사용하고 싶으면 abc.0 를 쓰면된다.

 

이번은 타입을 생략했는데 사실 튜플이라고 따로 뭔가 이름이 있지 않고 값에 따라 다르게 들어간다

위의 abc는

(Int, Dobule, String) 이라고 형식이 지정되었을것이다.

 

튜플은 꽤나 유용하게 쓰일수 있으나 자리수 0,1,이런식으로 부르면 

뒤에서 형식을 알아보기 힘들다.

 

그래서 튜플은 아래와 같이도 사용가능하다.

 

let abc = (number:4 , double:3.141592 , string: "abcdefg")

대신 이렇게 적었다면

첫번째 수에 접근하고 싶으면

abc.number 이렇게 적어줘야한다.

 

8. 옵셔널

이 옵셔널은 논리형과 비슷하나 실제값을 가지고있다.

옵셔널 자체는 값이 두가지로 나눠지는데

none 과 some 이다.

실제로 사용할때는 none은 값이 nil 으로 나오고

some은 실제 값이 나오게된다.

 

값을 저장하게끔 변수를 만들었으나 이게 진짜 값이 들어갔을지 모르는 상황에서 안전하게 값을 사용하게 만들어진 

안전장치중 하나이다.

 

이 옵셔널 형식은 거의 모든 형식에 붙일수있고 데이텨형뒤에 물음표를 붙여 지정한다.

 

실제 사용할때는 이 옵셔널을 벗기고 사용해야한다.

벗기는 방법은 느낌표를 붙여서 강제로 벗기거나

아직 다루지않은 조건문에 의해서 값이 none이 아니면, nil이 아니면 사용가능하도록 하게 할 수 있다.

 

강제로 벗길때는

 

var a:Int? = 4 

라면

let b = a!

이렇게 하면 b에는 4가 들어간다. 

 

9. 딕셔너리

6번, 배열과 유사하다.

6번에는 값이 넣은 순서대로 질서를 유지하는애라면

딕셔너리는 키값에 따라 팀을 이룬 값이다.

데이터형은 

Dictionary<키값의 형: 값의 형>

또는

[키값의 형 : 값의 형] 으로 적는다.

배열은 값을 넣은순서를, 인덱스를 넣었다면

딕셔너리는 키를 넣어서 값을 접근한다.

키가 없으면 없는 값이기에 딕셔너리는 접근시 반환되는 값이 옵셔널값이다.

 

let abe:[String:String] = [ "길동" : "111-434""길수" : "112-443"]

값을 출력할때 옵셔널을 해제하지 않으면 아래와 주석과같이 나온다.

print(abe["길동"]) // Optional("111-434")

 

- 위 줄은 그대로 적어도 동작한다 뒤에 '//'는 주석이라하여  코드에 적어놓는 메모이다. 

 

let abf:Dictionary<String,String> = [ "길동" : "111-434""길수" : "112-443"]

print(abf["길동"])

 

 

 

 

 

 

 

 

 

 

+ Recent posts