아두이노와 함께 하기 위한 간단한 Swift 지식들


이 글은 전문적으로 Swift를 학습하기 위한 것이 아니라 아두이노 개발과 관련하여 아이폰쪽 소스를
조금 더 잘 이해하고자 하는 목적입니다.


관련 소스 : https://github.com/mazdah/BluetoothController


1. 변수와 상수


let : 상수를 만들 때 사용하며 최초 한번 값을 할당하면 이후 값을 변경할 수 없음
var : 변수를 만들 때 사용


타입 지정은 필수가 아님
할당된 값은 암시적인 타입변환을 할 수 없음. 초기 값과 다른 타입으로 사용하기를 원한다면 
반드시 명시적으로 형 변환을 해주어야 함


문자열 안에 변수를(변수의 값을) 표현하고자 하면 다음과 같이 표현한다.
“문자열 안에 값을 쓰려면 \(변수명) 이렇게 쓴다”


배열과 딕셔너리는 []를 이용하여 만든다.


var sampleArray = [“a”, “b”, “c”, “d”, “e”]
var sampleDictionary = [
    “first”:”a”, 
    “second”:”b”, 
    “third”:”c”, 
    “fourth”:”d”, 
    “fifth”:”e”
]


빈 배열과 딕셔너리는 initializer를 사용한다.


let blankArray = String[]()
let blankDictionary = Dictionary<String, Float>()


타입을 명시적으로 사용할 수 없을 경우 다음과 같이 표기할 수 있다.


let blankArray =[]
let blankDictionary = [:]


2. 조건문


if의 조건문은 ()로 감싸지 않아도 된다. 하지만 코드를 감싸는 중괄호({})는 필수다.


if value == 1 {
    print("value = 1")
}


3. Optional


어떠한 변수나 상수에 값이 존재하는지 여부를 표현함
표현 방식은 다음과 같다.


var optionalInt: Int? = 100
var optionalString: String? = “this is optional String”
// 값을 초기화 하지 않으면 자동적으로 nil로 초기화 됨
var nilIn: Int?
var nilString: String?


어떤 optional이 값을 가지고 있으면 true, 값을 가지고 있지 않으면 false이다.


var optionalInt: Int? = 100

// 아래의 경우는 true가 출력된다.
if optionalInt {
	print("true")
} else {
	print("false")
}

var nilInt: Int?

 // 아래의 경우는 false가 출력된다.
 if nilInt {
	print("true")
 } else {
	print("false")
 }

nil은 optional이 아닌 상수나 변수와 사용할 수 없다.

Objective-c에서의 nil은 존재하지 않는 Object에 대한 포인터였다면 Swift에서의 nil은 포인터가 아닌 명확하게 값이 없다는 것에 대한 표현일 뿐이다. 때문에 어떤 타입에 대해서도 nil을 지정할 수 있다.


Optional binding


if문에서 다음과 같이 optional binding을 사용할 수 있다.


var optionalString = "123"

if let constantValue = optionalString.toInt() {
    println("\(optionalString) has an integer value of \(constantValue)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
} 


이 if문의 의미는 optionalString.toInt()가 리턴한 옵셔널 int가 값을 가지고 있을 경우 그 값을
constantValue에 할당하고 이후 constantValue는 ! 기호를 붙이지 않고 사용 가능하다.
optional binding은 변수와 상수에 모두 사용 가능하다.


Implicitly Unwrapped Optionals


만일 프로그램상에서 구조적으로 값이 있다는 것이 명확한 optional의 경우 ?가 아닌 !를 붙여
Implicitly Unwrapped Optional을 만들 수 있다.


//Optional
let possibleString: String? = "An optional string." 
// Implicitly Unwrapped Optional
let assumedString: String! = "An implicitly unwrapped optional string."


Implicitly Unwrapped Optional은 사용 시에도 Optional이 아닌 것처럼 사용할 수 있다.


//Optional의 사용
println(possibleString!)
// Implicitly Unwrapped Optional의 사용
println(assumedString)


Implicitly Unwrapped Optional도 Optional과 동일하게 if문을 통해 값을 가졌는지 체크하거나
optional binding 사용이 가능하다.


if assumedString {
    println(assumedString)
}

if let tempString = assumedString {
    print(tempString)
}


Optional 요약

  • 값이 없는 경우를 만들기 위해서는(nil을 할당하기 위해서는) Optional로 선언해야 한다.
  • Optional로 선언하게 되면 값이 Wrapping된다.
  • Optional 값을 사용하기 위해서는 Unwrapping 해야하는데 그 방법은 Optional 뒤에 !를 붙이는 것이다.
  • if문을 통해 optional binding을 이용하면 !를 붙이지 않고 다른 변수/상수에 값을 할당하여 그 변수/상수를 이용할 수 있다.
  • 최초 할당 이후 nil 값이 아닌 것이 확실한 경우 선언할 때부터 !를 붙이는 Implicitly Unwrapped Optional를 사용하며 이후 Optional이 아닌 것처럼 사용 가능하다.


블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

같은 계정으로 등록된 앱이어야 공유가 가능하며

앱 아이디의 prefix가 같아야 한다...


업무상 iOS용 앱 2개 중 하나가 다른 하나의 버전을 체크해야 할 상황이 되었는데

이게 아무리 해도 안된다.


원인은 메인 앱은 현재 근무하고 있는 곳 계정이고 다른 앱은 타 개발사 계정으로 만들어진 앱이기 때문이었다.

결국 계획 무산...-.-

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

사찰 풍경...

iPhone gallary 2013.08.05 13:50

우이동 어느 절에서...




'iPhone gallary' 카테고리의 다른 글

사찰 풍경...  (0) 2013.08.05
등(燈)...  (0) 2013.08.05
구름...  (0) 2013.08.05
서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

등(燈)...

iPhone gallary 2013.08.05 13:48

우이동 도선사...




'iPhone gallary' 카테고리의 다른 글

사찰 풍경...  (0) 2013.08.05
등(燈)...  (0) 2013.08.05
구름...  (0) 2013.08.05
서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

구름...

iPhone gallary 2013.08.05 13:45

구름이 멋진 날...




'iPhone gallary' 카테고리의 다른 글

사찰 풍경...  (0) 2013.08.05
등(燈)...  (0) 2013.08.05
구름...  (0) 2013.08.05
서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

어느 새벽 길에 마주친 풍경...




'iPhone gallary' 카테고리의 다른 글

등(燈)...  (0) 2013.08.05
구름...  (0) 2013.08.05
서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
봄의 시작...  (0) 2013.08.05
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

서울 을지로에서...




'iPhone gallary' 카테고리의 다른 글

구름...  (0) 2013.08.05
서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
봄의 시작...  (0) 2013.08.05
[옛 글] 봄맞이...  (0) 2013.07.19
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

사이 좋게..

iPhone gallary 2013.08.05 13:39

산정호수 어느 펜션에서...




'iPhone gallary' 카테고리의 다른 글

서울 누와르...  (0) 2013.08.05
도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
봄의 시작...  (0) 2013.08.05
[옛 글] 봄맞이...  (0) 2013.07.19
[옛 글] 겨울 풍경...#5  (0) 2013.07.19
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

봄의 시작...

iPhone gallary 2013.08.05 13:37

벌써 한참 전 사진이 되어버린...




'iPhone gallary' 카테고리의 다른 글

도시...그 웅장함  (0) 2013.08.05
사이 좋게..  (0) 2013.08.05
봄의 시작...  (0) 2013.08.05
[옛 글] 봄맞이...  (0) 2013.07.19
[옛 글] 겨울 풍경...#5  (0) 2013.07.19
[옛 글] 겨울 풍경...#4  (0) 2013.07.19
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

최초 작성일 : 2013/05/23 17:28


곧 완성을 앞두고 있는 신규 앱에는 야심차게(?) IAP(In-App Purchase:앱내 구매)를

구현해보기로 했다.

이유는 당근 유/무료 버전을 나누는 것 보다는 IAP가 더 수익성이 좋을 것 같았기 때문이다.
그래봐야 1년이 가도록 겨우 개발자 등록비 뽑는 수준이지만...ㅠ.ㅠ

우선 기본적인 구현은 문제가 없었다.
맥부기 회원들의 도움으로 쉽게 구현을 마쳤다.
그런데 문제는 애플 서버를 이용한 영수증 인증이다.
탈옥을 통한 일종의 해킹 방지 차원이랄까?

이를 위해 특별히 애플에서 기본 소스 코드도 배포를 하고 있다.
아래 링크로 가면 간단한 설명이 있는 페이지가 나오고 그 페이지의 우상단에 보면
Companion File이라고 링크가 걸려있는데 여기에 VerificationController.h와
VerificationController.m 요렇게 약소하게 파일 2개가 들어있다.


이 파일에 적절하게 코드를 추가하여 처리하면 된다.
일단 가장 자세한 설명이 있었던 맥부기의 글이 아래 링크에 있다.


대체로 이 글을 통해 구현을 완료하였는데...
문제는 관련 글에도 있지만 SANBOX로 테스트하던 것을 애플 리뷰 후
실 상품 서버로 연결해야 하는데 이 것을 어떻게 해야 하냐는 것과

기존 코드의 paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray*)transactions
통해 수행하던 내용 중 [[SKPaymentQueue defaultQueuefinishTransaction:transaction];   
요넘을 어떻게 처리하느냐가 문제였다.

두 번째 문제의 경우 뭐 대충 델리게이트 써가면서 어렵지 않게 해결하였다.
특히 두 번째의 처리를 하지 않으니 IAP 서버에서 상품을 가져올 때마다
이전의 트랜잭션들이 모두 함께 내려와서 문제가 되었기에 반드시 처리를
해주어야 했다.

그리고 어렵게 처리한 첫 번째 문제

우선 구조가 NSMutableURLRequest를 이용해 서버에 연결하는 내용인데
처리는 우선 실 상품 서버로 연결을 하고 거기서 실패를 할 경우 테스트용 SANDBOX로
연결을 해야 하는 것이었다.

만일 테스트 계정으로 실 상품 서버로 연결을 하여 처리하게 되면
connection:didReceiveData: 함수에 response되는 결과값으로 21007이 떨어지게 된다.

이 21007이 확인된 이후 어떻게 해야 하는지에 대한 설명이 아무데도 없어서
혼자서 열심히 쌩X랄을 하였다.

우선 구매 요청부터 다시 보내보았다. 그랬더니 구매 팝업이 2번 뜨는 우스운 모양이
되어버려 실패...

다음으로는 처음 구매 요청후 생성된 transaction을 전역변수에 넣고 다시 서버 연결부 부터
진행을 해보았다. 역시 실패...

그리고 마지막에 처리한 것이 다음 방법이다.

영수증 인증을 위해 NSURLConnection을 이용하여
인증 서버로 연결할 때 인자로 넘기는 것이 transaction의 transactionReceipt 속성을
이용하여 만든 NSData형의 값이다.

그래서 전역 변수로 NSData형을 만들고 transaction. transactionReceipt를 이용하여
만든 NSData 값을 이 전역 변수에 할당 한 후 실 상품 서버에서 21007이 떨어지면
요넘만 인자로 넘겨서 다시 NSURLConnection커넥션을 하니 잘~ 처리가 되었다.

이로써 무사히 IAP 구현을 마치게 되었다...^^

위 설명한 프로세스를 요약하면 아래와 같다.

***
참고로  ITC_CONTENT_PROVIDER_SHARED_SECRET라는 값을 설정하도록 되어있는데
아무리 찾아봐도 내 계정의 아이튠즈 커넥트 화면에서는 그 값을 받아오는 링크가
보이질 않는다...ㅠ.ㅠ

설정을 안해도 테스트는 잘 되던데...이게 테스트이기 때문에 잘 되는 것인지...
요게 쪼끔 걸리네...ㅠ.ㅠ

============================================

PCStoreViewController : IAP 구매 화면 및 구매 시작을 담당함

구매버튼 터치시 아래 내용 실행
//payment는 SKPayment 타입의 전역변수

payment = [SKPayment paymentWithProduct:self.product];

 [[SKPaymentQueue defaultQueue] addPayment:payment];


addPayment 메서드 실행 후 델리게이트인 아래 메서드 실행

- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions


이 함수 내에서 transactions를 루프 돌리면서 각각의 transaction에 대해
transaction.transactionState에 따라 처리를 하게 되는데 다음 2가지 경우에 대해
VerificationController의 verifyPurchase:transaction 메서드를 호출한다.

SKPaymentTransactionStatePurchased

SKPaymentTransactionStateRestored



VerificationController : 영수증이 유효한 것인지 애플 서버를 통해 인증

 verifyPurchase:transaction 메서드 내에서 인자로 넘겨받은 transaction의
transactionReceipt 속성을 이용하여 NSData형의 값을 NSURLConnection을 통해 서버로 넘김 이 때 인자로 넘어가는 NSData를 전역변수에 할당을 해놓아 이후 21007
코드에 대비를 한다.

NSURLConnection의 델리게이트 메서드인 connection:didReceiveData:에서 최종 구매처리를 한다.
response 값으로 넘어온 NSData형의 data는 NSDictionary로 변환할 수 있는
JSON 값이며 여기에는 receipt라는 키로 NSDictionary 타입의 값이 들어있는데
이 값에는 각종 구매 정보가 들어있다.

그리고 status라는 키로 NSNumber 타입의 상태 정보가 넘어오는데 앞서 설명했듯이
테스트 계정으로 구매를 하는데 실 상품 서버로 연결을 하게 되면 이 값이 21007이
넘어온다.

만일 이 status가 이상이 없으면 (0이면) 구매 완료 처리를 하고 추가로 만든
델리게이트 메서드를 통해 finishTransaction 처리를 한 후 IAP 화면을 닫도록 하였고

21007인 경우 verifyPurchase: 메서드에서 전역변수에 저장해놓은 NSData를
인자로 하고 서버 주소는 SANDBOX(테스트)용 주소로 하여 다시 NSURLConnection
연결을 시도한다.

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^