티스토리 뷰

2022.12.27 - [iOS개발/Swift 통신] - Swift Alamofire 간단 서버에서 값 가져오기 기본편

 

Swift Alamofire 간단 서버에서 값 가져오기 기본편

2022.12.26 - [iOS개발/Swift 통신] - Swift ObjectMapper 사용해보기 Swift ObjectMapper 사용해보기 일반적으로 통신을 하게 되면 서버에 무언가를 요청하거나 혹은 서버에서 값을 받아오게 되는데 이때 이를 도

world-of-larooly.tistory.com

위 포스트의 다음 글입니다. 

 

위 포스트에서는 상당히 간단하게 이야기가 되었는데 

실제로 사용하시려면 Header 라던지 Parameter 라던지 통신방식(post,get)도 설정해야 하고

생각보다 하셔야 할일이 많을 수 있어요. 

 

당연한 이야기이긴 합니다만 각각 통신 방식이나 약속이 다를 수 밖에 없고

저희는 그거에 맞춰서 통신을 만들어야 서버랑 데이터를 주고 받을 수 있겠죠?

(저는 문서가 있어서 그거에 맞춰서 만들었어요)

 

그리고 지금부터는 Http 와 통신을 할 예정이라 

info.plist 에 해당 부분을 추가해 YES로 설정해주세요.

Http 통신을 위해서는 반드시 해야합니다!

 

헤더 부터 천천히 해봅시다.

각각의 부분을 설정 후 통신하는 부분을 마지막으로 볼께요.

 

*세부사항은 서버마다 요구하는게 다릅니다.*

*형식만 참고해주세요.*

 

Headers 

- 헤더는 이런 식으로 딕셔너리 타입으로 만드신다고 생각하시면 됩니다. 

- HTTPHeaders 가 안뜨시는 분들은 "import Alamofire" 하셨는지 확인 해주세요.

 let apiHeader: HTTPHeaders = [ "x-client" : "ProjectName",
                               "User-Agent": "iOS",
                               "Content-Type" : "application/json"]
// 세부 사항은 서버 설정마다 다릅니다.
// 형식만 참고해주세요.

URL

- URL 은 여러분들이 원하시는 URL을 String 으로 넣어주시면 됩니다. 

 

method

- 원하시는 통신 방식을 선택해주시면 됩니다.

- .post / .get / .delete / .put  보통 이 4개 중에서 많이 씁니다. 

- 저 4개중 원하시는 걸로 골라 써주시면 됩니다. 

 

parameters

- 서버에 보내는 값입니다. 여기는 진짜 형식이 다양하기 때문에 잘 확인하셔야 합니다. 

- 여기 부분의 형식을 잘 활용하셔야 합니다 (이것때문에 ObjectMapper 이야기 한거였어요.)

- 여기서 잘못하면 서버에는 빈값이 전달되게 됩니다. 조심하세요!

- 2022.12.26 - [iOS개발/Swift 통신] - Swift ObjectMapper 사용해보기

let parameterSample = a_param as? Parameters
// 여기서 a_param 은 주로 [String : Any]로 구성되있습니다.

헷갈릴수있으니 추가 설명드릴께요. 

예를 들어 {userId : String , date : String , answer : [String]} 이 형식을 보낸다고 하면 

저라면 아래처럼 형식을 선언하고 (아래는 ObjectMapper 를 사용한 겁니다.)

// ObjectMapper 를 이용한 방식입니다.
// 따라하실분들은 ObjectMapper를 추가해주세요.(위 링크글 참고)
class postWord : Mappable{
    var userId : String?
    var date : String?
    var answer : [String]?
    
    required init?(map: Map) {
    }
    func mapping(map: Map) {
        self.userId <- map["userId"]
        self.date <- map["date"]
        self.answer <- map["answer"]
    }
}

아래처럼 선언해서 보낼껍니다.

(그냥 String 의 경우에는 괜찮은데 배열이나 특이한 케이스가 섞이면 가끔 안보내지는 경우가 있어서 그래요)

let answerSend = ResquestSetWord(JSON: ["userId":"abcdefg",
                                        "answer": ["1","2","3"],
                                         "date":"2022-12-29"])
                                                 
let paramSample = answerSend?.toJSON()

각 서버에 맞게 잘 만드셔서 보내야 합니다!

 

encoding

- 많이 쓰이는 거 두가지만 소개할께요. 

- JSONEncoding.default / URLEncoding.default

- 설정에 따라서 받아온 값이 보이거나 안 보일 수 있으니 주의해서 사용해주세요.

 

합치기

- 이제 설정할걸 다했으니 보내면 되겠죠? 

// apiHeader : 아까 처음에 설정한 Header
// a_url : 통신할 URL
// a_param : 서버에 보낼 값들을 입력하면 됩니다.
// completionHandler : 받아온 데이터 값을 다른곳에서 처리하기위해 추가 

public static func reqestData(apiHeader: HTTPHeaders, a_url: String, a_param: Any?, completionHandler: @escaping (_ response: [String: Any]) -> ()) {

	AF.request(a_url, method: .post, parameters: a_param as? Parameters, encoding: JSONEncoding.default, headers: apiHeader).responseData{ response in

            switch response.result {
            case .success(let data):
                do {
                    let value = try JSONSerialization.jsonObject(with: data , options: .mutableContainers)
                    print(value)
                    guard let castingValue = value as? [String: Any] else {return}
                    completionHandler(castingValue) // 받은 값은 다른곳에서 처리
                }catch {
                    print("get special error")
                }
            case .failure(let error):
                print(error.localizedDescription)
            }
        }.downloadProgress(){progress in // 진행상황을 보이게 하기위해 
            print("percent : \(progress.fractionCompleted)")
        }
    }

@escaping 이 뭔가요?

해당 함수에서 나온 결과값(혹은 특정값)을 여기서 가공하는게 아니라 그때그때 상황에 따라 가공해 쓰겠다는 의미입니다. 

해당 함수를 선언하고 결과값을 각 구역마다 다르게 처리해야하는 경우 쓰이게 됩니다. 

 

예를 들어 위의 경우를 활용하면 실제로는 아래처럼 쓸수있습니다. 

class ResponseSetWeight: Mappable{
    var succ : Bool? // 성공 여부
    
    required init?(map: Map) {
    }
    func mapping(map: Map) {
        self.succ <- map["succ"]
    }
}

// 아래 식처럼 값을 데려올수있습니다.
NetWorkBase.reqestData(apiHeader: "설정한 헤더",a_url: "setWeight", a_param: parameters){ response in
    //여기서부터 결과값 가공하는 부분
    guard let responseData = Mapper<ResponseSetWeight>().map(JSON: response) else { return }
    if(responseData.succ == nil){
        print("startSetWeight : Fail")
        return
    }
    if(!responseData.succ!){//실패
        print("startSetWeight : Fail")
        return
    }
    print("startSetWeight : Succ")
}

 

통신 부분은 처음에 하실때는 어렵다고 느끼실 수 있지만

하나씩 천천히 보면 충분히 하실 수 있습니다. 

 

값이 잘 안나오신다면 설정 값을 바꿔보시는 것도 방법입니다. 

(특히 encoding / method 부분이 잘못설정되면 값이 안 나올 수 있습니다.)

 

이해하기 쉽게 글을 최대한 작성해보려했는데 

잘 안되네요;;

도움이 되셨으면 좋겠는데...

 

다음 편에는 사진 전송에 관해서 이야기 해볼께요. 

 

아무튼 

오늘도 파이팅입니다.

 

댓글