반응형

swift로 iOS WEB APP을 만들다보면  웹과 앱 사이 통신이야 javascript로 서로 통신을 하니 별 문제가 없는데
앱 이용자와 일반 모바일 웹 이용자의 화면 UI를 다르게 제공할 일이 존재한다.
가령 GNB에 앱 설정을 불러오는 버튼은 앱 이용자에게만 지원할 때 인데 모바일 웹에선 앱의 기능 설정할 일이 없을테니 말이다.
useragent로 확인을 한들 사파리 브라우저로 접속 하든 앱의 wkwebview로 접속 하든 아주  아니 똑같다.

어쩔 수 없다.
앱으로 접속할 땐 url을 호출할 때 custom agent로 agent를 마사지 해줘야 한다.


webView.evaluateJavaScript("navigator.userAgent") {(result, error) in 
let originUserAgent = result as! String
    let customAgent = originUserAgent + " IOSAPP"
    self.webView.customUserAgent = customAgent 
}

이렇게 보내주고 웹에서 agent를 분석할 때 IOSAPP이 존재하면 아하 우리 회원님이 앱을 사용하고 계시는구나~ 하며 앱용 기능을 제공하면 되겠다.

물론 앱에서 웹쪽으로 "이보시게 관상가 양반. 내가 앱이 될 상인가?" 라며 JAVASCRIPT 함수 하나를 서로 약속하고 호출하면 웹에선 이를 쿠키로 저장하든 세션으로 저장하든 하여 "성군 앱이 되실 분 이십니다."라며 처리해도 무방하나 좀 없어보인다.

반응형
Posted by Hippalus
,

반응형

//먼저 이런 파일명이 존재한다 치자 일부러 .을 파일명에도 넣었다.
var strData = "동해물과. 백두산이.txt"

// 파일명과 확장자를 .으로 분리한다.
if let lastDotIndex = strData.lastIndex(of: ".") {
    let fileNameWithoutExtension = String(strData[strData.startIndex..<lastDotIndex])
    print(fileNameWithoutExtension) // 출력: "동해물과. 백두산이"
} else {
    print("확장자가 없는 파일명입니다.")
}

// 다음은 원하는 자릿수부터 자릿수까지 추출한다.
// 1번째 글자부터 (0이면 처음임) 8번째 자리까지 추출한다.
let startIndex = strData.index(strData.startIndex, offsetBy: 1)
let endIndex = strData.index(strData.startIndex, offsetBy: 3)

let extractedSubstring = strData[startIndex..<endIndex]

print(extractedSubstring) // 해물

반응형
Posted by Hippalus
,

반응형

간단히 사람배열과 그 사람의 보유금액배열을 스위프트로 생성해 보겠다.
사람배열은 문자열형, 보유금액배열은 Int형이다.

var arrPerson:[String] = []
var arrMoney:[Int] = []

// 한명씩 append시키고
arrPerson.append("홍길동")
arrPerson.append("고길동")
arrPerson.append("둘리")

//순서대로 보유금액을 append시킨다.
arrMoney.append(10000000)
arrMoney.append(30000000)
arrMoney.append(0)

//이제 dictionary를 선언한다. key, value는 String,Int형이다. key에는 이름이 value에는 금액이 들어갈 것이다.
var dicData = [String:Int]()

//사람과 보유금액의 배열은 1:1이므로 사람이든 금액이든 아무 배열이나 잡고 돌리면 되지만 난 사람 배열로 돌린다.
for i in 0..<arrPerson.count {
    //dictionary의 key에 사람배열의 값, value에 보유금액의 값을 저장한다.
    dicData[arrPerson[i]] = arrMoney[i]
}

// 출력해보면 순서대로 홍길동 10000000, 고길동 30000000, 둘리 0이 찍히는것을 확인할 수 있다.
for (key, value) in dicData {
    print("\(key) : \(value)")
}

print("정렬 후 결과")

// 이제 정렬을 해보자
// 오름차순정렬이고 만약 내림차순이 하고싶다면 $0.1 < $1.1 대신 $0.1 > $1.1바꿔주면 된다.
// 참고로 0.1, 1.1은 첫번째 인자의 value 두번째 인자의 value를 뜻한다.
// 결과는 튜플로 반환가능하다.
var tupSortResult = dicData.sorted {$0.1 < $1.1}

//print해보면 정렬된 상태로 확인된다.
//[(key: "둘리", value: 0), (key: "홍길동", value: 10000000), (key: "고길동", value: 30000000)]
print("\(tupSortResult)")

//for문을 통해 돌려가며 찍어보면 아래처럼 보여진다.
// 둘리 0
// 홍길동 10000000
// 고길동 30000000
for i in 0..<tupSortResult.count {
    print("\(tupSortResult[i].key) \(tupSortResult[i])")
}

반응형
Posted by Hippalus
,

클로저 기초 2

swift 2023. 7. 11. 05:48

반응형

본 포스팅은 남 포스팅을 공부하며 정리한 내용이다.
원본 강좌 포스팅은 아래를 참고
(https://www.boostcourse.org/mo122/lecture/11297?isDesc=false)

클로저를 포함해 요즘것들은 뭐가 그리 잘났다고 줄여대는지 도덕책 근본이 없다.
개발은 평생 지 혼자 싸들고 하나
남 생각도 할 줄 알아야 그기 사람 아이가 그기 마!

클로저는 다양하게 표시할 수 있는데 일단 클로저를 받아줄 함수를 선언하자
Int형의 인자 a, b 2개를 받고 클로저를 받을 method마찬가지로 Int형 2개와 리턴형은 당연히 Int다
콩에는 콩 팥에는 팥이다.

func calc(a:Int, b:Int, method:(Int, Int)-> Int) -> Int{
    return method(a, b)
}

후행클로저
위 calc라는 함수의 마지막 파라메터가 클로저가 함수의 마지막 인자일 때 가능하며, 마지막 파라메터의 이름을 생략할 수 있다.
이렇게
result = calc(a:10, b:10) {(left:Int, right:Int) -> Int in
    return left + right
}

반환타입 생략
상식적으로다가 파라메터가 Int가 넘어왔으면 Int를 리턴해준다라는것 정도는 컴파일러가 알기 때문에 리턴 타입인 -> Int는 생략해도 되겠다.
다만 in은 삭제 불가

이렇게 호출해야 하는걸
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

method를 날려줄 수 있고
result = calculate(a: 10, b: 10), method: { (left: Int, right: Int) -> Int in
    return left + right
}

-> Int도 날려줄 수 있다.
result = calc(a:10, b:10) {(left:Int, right:Int) -> Int in
    return left + right
}

최종 결과물은 이러하다.
retult = calc(a:10, b:10) {(left:Int, right:Int) in   
    return left + right
}

위에 단축한 결과와
아래 원래 
result = calc(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

단축 인자 이름
result = calc(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

result = calc(a: 10, b: 10) {
    return $0 + $1
}

암시적 반환
한줄로도 표현이 가능한데...
클로저가 반환값이 있다면 클로저의 마지막 줄 결과값을 암시적으로 반환값으로 치부하여 return 없이도 return
뭔 홍길동 호부호형도 아니고 리턴을 왜 리턴이라 하지 못하는지.
깔끔은 하지만 좀 그렇다.
result = calc(a: 10, b: 10) { $0 + $1 }

반응형

'swift' 카테고리의 다른 글

클로저 기초 1  (0) 2023.07.10
swift int 변수를 string형으로 변환 그리고 비교  (0) 2018.11.21
Posted by Hippalus
,

클로저 기초 1

swift 2023. 7. 10. 23:14

반응형

클로저 공부 중 정리와 암기를 위한 타이핑용 포스팅이며 원본은 야곰이란 분의 포스팅을 보는걸 추천함
(https://www.boostcourse.org/mo122/lecture/11296)
컴파일러 없이 웹상에서 간단하게 playground 환경으로 테스트 하기 위한 경우 아래 링크에서 swift 문법 테스트가 가능함
https://www.onlinegdb.com/online_swift_compiler

클로저란?
실행가능한 코드 블럭
일급객체로 변수, 상수, 전달인자 등에 저장은 물론 전달이 가능
클로저는 이름이 있는 클로저와 이름이 없는 클로저로 존재
함수도 클로저의 일종으로 이름이 클로저임
함수와 다르게 이름 정의는 필요하지 않고, 매개변수 전달과 반환 값이 존재 할 수 있다란 점은 동일함

클로저 기본 문법
{(매개변수 목록) -> 반환타입 in
    실행코드
}

클로저 기본 사용 방법
var든 let이든 상관없이 선언 후 선언된 변수나 상수에 클로저를 할당하면 됨
var printName:(String, String)->String = {(firstName:String, lastName:String) in
    return firstName + lastName
}
1. var printName printName이란 변수를 선언
2. (String, String)->String String형태로 인자 2개를 받고 이를 String형태로 리턴해준다란 의미
3. firstName:String, lastName:String 인자 이름은 첫번째가 firstName, 두번째가 lastName
4. 실행코드의 구분은 in 전후로 나뉘고 실행코드는 return firstName + lastName 이므로
    넘겨받은 첫번째, 마지막 이름을 연결해서 리턴해줌

함수의 전달인자인 클로저
클로저는 주로 함수의 전달인자로 많이 사용된다 함.
함수 내부에서 코드블럭을 실행 할 수도 있다 함.
그런데 뭔말인지 모르겠음. 쉽게 생각해보면 작고 귀엽고 간단한 클로저를 하나 먼저 만들고
이 귀염뽀찍 클로저를 다른 함수에 전달해서 함수에서 호출하고 지지고 볶는 그런 느낌인가 봄
먼저 4칙연산 중 덧셈 클로저를 만들어보겠음
let add: (int, int) -> int
뭔가 이상하지 않음?
int의 i가 대문자여야 함 다시 작성하겠음(이러면서 문법과 친해지는거임)
let add: (Int, Int) -> Int
add = { (a: Int, b: Int) in
    return a + b
}

위처럼 작성해도 되고 아래처럼 작성해도 됨

let add2: (Int, Int) -> Int = {(a: Int, b: Int) in
    return a + b
}

아직까진 swift가 지멋대로 축약질에 변동성이 너무 강해 짜증이 남.
요즘 언어들은 싸가지들이 없음.
근본이 없음. 지들만 잘난냥 떠들어재끼는 MZ들처럼

함수를 만들어줌
a,b를 인자로 Int형을 받고 아까 말했듯이 클로저를 함수에 전달할 수 있으니 이부분을 method라는 이름으로 구현해줌
func calc(a:Int, b:Int, method:(Int, Int)->Int)->Int {
    return method(a, b)
}
조금 분해해서 살펴보면
함수니까 func라고 쓰고 함수이름 아무거나정해서 calc라고 적었음
함수니까 괄호열어주고 (
전달받는 인자는 2개 그다음이 클로저인데 앞서 add클로저를 보면 let add: (Int, Int) -> Int 임
여기에서 let add: (Int, Int) -> Int 앞에 let add어쩌구는 제끼고 그 뒤엣것만 가지고 온거임
함수니까 괄호닫아주고 )
그리고 리턴형이 Int니까 -> Int 써준게 전부
그 다음은 함수 실행부이니 전달받은 클로저를 전달한 인자 a,b로 그냥 실행 method(a, b)

함수까지 만들었으니 이제 실행하면 됨.
먼저 Int형 변수 하나 선언해주고
var nCalcResult:Int

이 변수에 아까 만든 calc라는 함수를 불러와 넣어줌
이때 method는 클로저인 add 클로저를 호출하면 됨
nCalcResult = calc(a:1, b:1, method:add)

그럼 결과는 
print(nCalcResult) 
2

당연하겠지만 아까 조금 다르게 만든 클로저인 add2를 호출해도 결과는 동일하게 2로 잘 나옴
nCalcResult = calc(a:1, b:1, method:add2)
print(nCalcResult)

덧셈을 해봤으니 이제 뺄셈 나눗셈 곱셈 등을 동일한 방식으로 구현해보면 됨
let substract:(Int, Int) -> Int = {(a:Int, b:Int) in 
    return a - b
}
이렇게 하면 되고
처음에서처럼 아래처럼 하면 됨
let substract:(Int, Int) -> Int
substract = {(a:Int, b:Int) in
    return a - b
}

여전히 익숙하지 않은자를 위해 클로저 문법 안 까먹고 익히는 비법 공유함.
똑같이 반복해서 구간 구간을 점차 완성시키는 방식으로 스스로 타이핑 해보길 강권함.
let 
let substract
let substract:() -> 
let substract:(Int, Int) -> Int
여기까지가 1절 완성임

substract = {
}
substract = {()
}
substract = {(a:Int, b:Int)
}
substract = {(a:Int, b:Int) in
    return a - b
}

최종
let substract:(Int, Int)->Int
substract = {(a:Int, b:Int) in
    return a - b
}

이거 따라했으면 절대 안 까먹음
응용 복습하는 생각으로 나눗셈 만들기 스타또
let divide:(Int, Int) -> Int
divide = {(a:Int, b:Int) in
    return a / b
}

정말 마지막으로 곱셈
let multiple:(Int, Int) -> Int
multiple = {(a:Int, b:Int) in
    return a * b
}

이쯤되면 아까 함수 만드는거 까먹었을 거
func calc(a:Int, b:Int, method:(Int, Int) -> Int) -> Int {
    return method(a, b)
}

var nCalcResult: Int
nCalcResult = calc(a:10, b:2, method:divide)
print(nCalcResult)

곁다리로
클로저 표현을 let add:(Int, Int) -> Int = {(Int:a, Int:b) in 대신에 Int를 빼고 이렇게도 가능함
let add:(Int, Int) -> Int = {(a, b) in
    return a + b
}

반응형

'swift' 카테고리의 다른 글

클로저 기초 2  (0) 2023.07.11
swift int 변수를 string형으로 변환 그리고 비교  (0) 2018.11.21
Posted by Hippalus
,

반응형

애플이 망조가 들었는지 요즘 헛발질이 너무 잦습니다.

Xcode로 손쉽게 앱을 업로드 할 수 있지만 가끔가다 이런 오류를 내뱉더니 이번 Xcode7 이후 첫 업로드는 몇번을 해도 도무지 될 생각이 없습니다.


찾아보니 개발사 커뮤니티에서도 유사한 증상을 호소하는 개발사들이 많은것으로 확인되기에 이번 itunesconnect.apple.com 개편 이후 뭔가 꼬였나 봅니다.

상황이 이러하니 앱 심사를 더이상 미룰 수 없기에 Application Loader를 통해 업로드를 시도한 결과 다행히 앱이 정상 업로드 됨을 확인 할 수 있었습니다.


일단 Application Loader(어플리케이션 로더)를 통해 올리려면 ipa파일을 생성해내야 합니다.

Xcode > Product 메뉴 > Archive를 눌러줍니다. (여기까진 Xcode로 앱스토어 심사 업로드 방식과 동일)


Upload to App Store... 버튼 대신 Export를 눌러줍니다.


그럼 ipa파일을 저장할 폴더를 선택할 수 있습니다.

전 바탕화면에 저장하였습니다.


Application Loader를 실행시켜줍니다. 

Application Loader가 없다면 itunesconnect.apple.com의 심사 파일 선택하는 곳에서 다이렉트 다운로드 링크가 존재하니 해당 링크를 통해 설치 하면 됩니다.(정상 설치하였다면 Finder의 응용프로그램 폴더 안에서 찾을 수 있습니다.)

설치가 되었단 가정하에 실행하면 요런 화면이 실행됩니다.



App 전송을 눌러 앞서 저장했던 ipa파일을 선택하여 전송합니다.

그럼 아래처럼 iTunes Store로 업로드가 됩니다.



그런데

말입니다.

예전엔 (약 한달 전 까지만 해도) Xcode든 Application Loader든 업로드를 하면 10분내로  파일을 선택할 수 있었는데 말입니다.

이번엔 좀 다릅니다. 10분이 지나도 계속 처리 중 이란 상태가 지속됩니다. 50분동안~




구글링을 해보면 "처리 중" 상태가 지속된다란 고통을 호소하는 프로그래머 성님들의 절규를 발견할 수 있었습니다.

http://stackoverflow.com/questions/27928471/my-prerelease-app-has-been-processing-for-over-a-week-in-itunes-connect-what

(이런 경우가 전 처음이라 당황했지만 이 분은 하루가 지나도록 감감 무소식이라더군요. ㄷ ㄷ ㄷ)


애플 개발자 센터에 전화로 문의를 하였더니 원래 24시간 정도 걸릴 수 도 있다고 하더군요.

그러며 혹시 모르니 사파리로 해보았느냐 묻길래

gateway 446 떠서 크롬으로 했다고 답하니

이리 저리 묻더니 스크린샷을 보내달라 하더군요. 하지만 여기서도 애플의 갑질은 또 반복됩니다.

반드시 사파리로 실행한 스크린샷을 보내야만 한다합니다. 대애애애박!~

하여 사파리로 하는 차에 우연하게도 처리 중 상태가 사라지고 업로드한 파일을 선택 할 수 있게 되어 통화를 서둘러 종료를 하였다는 소식입니다.



반응형
Posted by Hippalus
,