I don't remember when this issue was first discovered, but I'm having trouble logging in to xcode with my Apple ID, but beta version works. (seems to be related to macOS big sur beta 11)
To submit app i need to figure this out asap. I googled and found some kind of trick.
restore api를 호출하면 observer delegate로 restored 상태를 가진 트랜잭션 목록이 전달됨
non-consumable or auto-renewable subscriptions 를 구입한 이력이 있으면 해당 identifier의 트랜잭션이 restored 상태값을 가지고 전달됨
필요에 의해 서버 처리하고 마지막은 무조건 finishedTransaction api를 호출해야 함 -> 트랜잭션 처리가 완료되었음을 알려주어야 함.
SKPaymentQueue
신뢰도 있는 state를 가지고 있는 유일한 소스
queue가 알려주는 payment가 실제로 유효하고 존재하는 payment이다
개발자가 캐싱할 수는 있지만 믿을 수 있는건 paymentQueue에 있다
앱 시작하자마자 payment queue를 트래킹하는 observer를 생성해라
이유에 대해 설명하기 위해 예를 들면, 리딤 코드를 발급하는 서비스의 경우 사용자는 앱 내가 아닌 앱스토어에서 리딤코드를 사용할 것이다. 만약 앱이 실행 되었을 때 바로 이를 알아채지 못하면 사용자는 해당 상품을 사용할 수 없게 된다. 따라서 앱이 실행되자마자 paymentQueue가 알아챌 수 있게 appDelegate에 launch delegate method에 observer를 생성해야 한다.
Error Handling
모든 에러가 같지 않기 때문에 가이드 문서 보고 에러 코드 체크할 것
에러에 대한 얼럿은 비추
사용자가 구매를 취소한 것도 에러 콜백을 호출한다
사용자는 본인이 캔슬한걸 알고 있는데 굳이 얼럿으로 또 확인 시켜줄 필요는 없다
트랜잭션 핸들링은 최대한 스토어킷이 하도록 놓아두자
Receipt Validation
Server to Server : downloadable service
on device : 단순히 클라 사이드에서만 체크해서 상품을 unlock하는 경우, 예를 들어 잘 만들어진 앱의 예는 아니지만 교육 동영상 목록을 어플 안에 모두 넣어두고 구입한 경우에만 플레이할 수 있도록 구현. 용량이 적고 서버를 구축할 상황이 아니었음. 이때 receipt validation을 클라에서 처리
receipt validation api는 절대 클라에서 직접 호출하지 말 것. 클라에서 보내는 것을 믿을 수 있는지 확인할 길이 없다
The receipt
이 디바이스에서 이 유저가 이 상품을 구매했는지 믿을 수 있는 정보를 제공
번들에 저장되어 있는 앱스토어 path로 receipt를 가져올 수 있음
절대 certificate의 expiry date로 만료일 체크하지 말 것
root certificate authority on the receipt로 체크할 것; 애플에서 왔지~
receipt는 물건을 구매하면 발생하는데 renewable하다
Transaction LifeCycle
Counsumable & Non-renewing Subscriptions : 구매 후 단 한번 트랜잭션 발생 refresh receipt하거나 디바이스를 변경해도 다시 발생하지 않는다
Non-Consumable & Auto-renewable Subscriptions : 언제나 receipt에 구매 이력이 남아 있다 restore api로 가져올 수 있다
리뷰 통과하려면
You must have a Restore button Should be used only for Non-Consumable & Auto-renewable Subscriptions
Resotre 와 구매 버튼은 따로
Auto-renewable 을 지원할 때 privacy policy URL 제공
앱 올릴때 지원한다느 걸 꼭 언급해야 함
계정로그인이 기본인 서비스가 아닌 경우 Non-renewing subscription은 로그인하지 않아도 구입할 수 있는 옵셔널 상품이어야 한다
주로 사용하는 개인 메일을 지난 회사에서 Apple Developer Program Membership에 추가해서 쓰고 있었다.
그러다 동료가 퇴사하면서 내 계정이 자연스레 팀의 placeholder가 되었다. 팀명이 전 개발자의 이름이었는데 그때는 그러려니 했는데 이직하니 문제가 생겼다. 우선 새로운 회사에서 새 membership에 메일을 추가하니 내 계정에 team이 두개가 되었고 내가 certificate를 revoke할 때마다 내 이름 대신 그 분의 이름(팀명)이 뜨면서 사람들이 누가 revoke 했는지 계속 확인하게 만든 것이다.
회사 옮길 때마다 이럴 수는 없기에 애플에 삭제 또는 팀명 변경이 가능한지 물어보니 상황을 이해는 하지만 불가능하단다.
개발 프로그램마다 하나의 이메일을 쓰라고 한다.
이런, 이직할 때마다 하나의 메일을 버리게 되다니... 이럴 줄 알았다면 회사 메일로 등록할 것을 그랬다.
[전개]
메인 메일을 새로 파자 결심하고 우선 개발 메일을 회사의 것으로 변경하기로 한다.
1. Apple Developer Program Membership에 추가된 이전 계정을 지우고 새 계정을 추가했다.
2. Xcode의 Preferences > Accounts 에서 Apple Id를 새로 업데이트했다.
[위기 & 결말]
잉? Xcode를 오픈할때마다 계정정보가 사라진다.
구글링해보니 키체인에 남아 있어서라고 해서 KeyChain Access > All items에서 이전 계정을 지우고 다시 시도했다.
오, 변경된 아이디로 뜬다.
앗, Update Signing에 에러가 떠있다.
Team ZXXXXXXXXX (Automatic) | Platform iOS
The operation couldn’t be completed. Unable to log in with account 0000@gmail.com'. (The login details for account '0000@gmail.com' were rejected.)
Code Sign이라... 한참 생각하다가 certificate 갱신을 떠올렸다.
새로 받아 설치하니 에러도 사라졌다.
그런데 문제가 하나 더 있었다.
Xcode Server로 CI를 돌리고 있는데 자꾸 한번 돌리고 나면 developer teams 에서 빠진다.
'your server has been removed from this team and needs to be added again' 에러가 뜬다.
regular expression을 이용해서 해시태그를 가져오는 메소드가 이모지가 있는 텍스트에서 제대로 동작하지 않는다.
NSRegularExpression을 사용하기 위해서는 NSString으로 형변환해야 하는데 NSRange에 문자열 길이를 NSString의 length가 아니라 String의 count로 넘겨주고 있었다.
NSString과 String은 유니코드에 대한 동작 방식이 달라서 반환하는 문자열 길이가 다르다. String은 Extended Grapheme Clusters 사용해서 이모지 하나를 문자 한개로 계산하고 NSString은 이모지 하나를 유니코드 문자 두개로 계산하기 때문이다.
(뒤늦게 깨닫기 있기?)
p (textView.text as NSString).length // print 6
p textView.text.count // print 2
NSString의 length를 인자로 넘기도록 수정하면 이슈 해결!! 개발할 때 주의하자...
objective-c에서 스위프트로 선언된 클래스, 메소드, 밸류 프로퍼티 등을 참조하고 싶을 때 @objc 프로퍼티를 지정해 주면 된다.
기존에 만들어진 어플에 스위프트로 작업하고 있기 때문에 @objc 프로퍼티를 쓸 일이 잦은데 swift4 부터 @objcMembers 라는 프로퍼티가 생겼다.
기존의 @objc와 다른 점이 무엇인가 찾아보니 다음과 같이 명시되어 있다.
When a Swift class introduces many new methods or properties that require behavior from the Objective-C runtime, use the@objcMembersattribute in the declaration of that class. Applying the@objcMembersattribute to a class implicitly adds the@objcattribute to all of its Objective-C compatible members. Because applying the@objcattribute can increase the compiled size of an app and adversely affect performance, only apply the@objcMembersattribute on declarations when each member needs to have the@objcattribute applied.
@objc는 파일 사이즈와 성능에 영향을 준다니 @objcMembers로 쓰지 않을 이유가 없다.
단, @objcMemebers는 클래스에만 사용할 수 있기 때문에 특정 method나 프로퍼티만 공유하고 싶을 땐 @objc 그대로 사용하면 된다.