-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from kyu-kim-kr/feature-Network
Feature network
- Loading branch information
Showing
100 changed files
with
16,361 additions
and
15 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
10 changes: 10 additions & 0 deletions
10
iOS/Baseball/Baseball.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
iOS/Baseball/Baseball.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?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>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// | ||
// GameEntity.swift | ||
// Baseball | ||
// | ||
// Created by 심영민 on 2021/05/06. | ||
// | ||
|
||
import Foundation | ||
|
||
struct GameList: Decodable { | ||
var gameNumber: Int | ||
var home: String | ||
var away: String | ||
} | ||
|
||
struct Game: Decodable { | ||
var home: Team | ||
var away: Team | ||
var homeScore: Int | ||
var awayScore: Int | ||
var inning: Int // 몇회 | ||
var status: String // 초, 말 | ||
var ballCount: [BallCount] | ||
} | ||
|
||
struct Team: Decodable { | ||
var name: String | ||
var players: [Player] | ||
} | ||
|
||
struct Player: Decodable { | ||
var name: String | ||
var position: String // 포지션 | ||
var atBat: String // 타석 | ||
var hits: Int // 안타 | ||
var out: Int // 아웃 | ||
var battingAverage: Double // 타율 | ||
var numberOfPitches: Int // 투구수 | ||
} | ||
|
||
struct BallCount: Decodable { | ||
enum ball: Int, Decodable { | ||
case strike = 0 | ||
case ball = 1 | ||
case hit = 2 | ||
} | ||
var ballCount: [ball] | ||
var hit: Bool | ||
} | ||
|
||
struct Score { | ||
var home: [Int] | ||
var away: [Int] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// FetchGame.swift | ||
// Baseball | ||
// | ||
// Created by 심영민 on 2021/05/06. | ||
// | ||
|
||
import Foundation | ||
import Combine | ||
|
||
class FetchGame { | ||
|
||
private var network: Network | ||
private var requestable: Requestable | ||
private var subscriptions = Set<AnyCancellable>() | ||
|
||
init() { | ||
self.network = Network() | ||
self.requestable = GameAPIEndpoint(path: "", httpMethod: .get) | ||
} | ||
|
||
func fetchGame(completion: @escaping (GameDTO)->Void) { | ||
network.request(with: requestable, dataType: GameDTO.self) | ||
.sink { (result) in | ||
switch result { | ||
case .failure(let error): | ||
print(error) | ||
case .finished: | ||
break | ||
} | ||
} receiveValue: { (game) in | ||
completion(game) | ||
} | ||
.store(in: &subscriptions) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// FetchGameList.swift | ||
// Baseball | ||
// | ||
// Created by 심영민 on 2021/05/06. | ||
// | ||
|
||
import Foundation | ||
import Combine | ||
|
||
class FetchGameList { | ||
|
||
private var network: Network | ||
private var requestable: Requestable | ||
private var subscriptions = Set<AnyCancellable>() | ||
|
||
init() { | ||
self.network = Network() | ||
self.requestable = GameAPIEndpoint(path: "", httpMethod: .get) | ||
} | ||
|
||
func fetchGameList(completion: @escaping (GameListDTO)->Void) { | ||
network.request(with: requestable, dataType: GameListDTO.self) | ||
.sink { (result) in | ||
switch result { | ||
case .failure(let error): | ||
print(error) | ||
case .finished: | ||
break | ||
} | ||
} receiveValue: { (gameList) in | ||
completion(gameList) | ||
} | ||
.store(in: &subscriptions) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
|
||
import Foundation | ||
|
||
struct GameDTO: Decodable { | ||
private (set) var game: Game | ||
} | ||
|
||
struct GameListDTO: Decodable { | ||
private (set) var gameList: GameList | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// | ||
// EndPoint.swift | ||
// Baseball | ||
// | ||
// Created by 심영민 on 2021/05/06. | ||
// | ||
|
||
import Foundation | ||
|
||
protocol Requestable { | ||
var baseURL: String { get } | ||
var path: String { get } | ||
var httpMethod: HttpMethod { get } | ||
func url() -> URL? | ||
} | ||
|
||
public struct GameAPIEndpoint: Requestable { | ||
|
||
public let baseURL = "" | ||
public let path: String | ||
public let httpMethod: HttpMethod | ||
|
||
init(path: String, httpMethod: HttpMethod) { | ||
self.path = path | ||
self.httpMethod = httpMethod | ||
} | ||
|
||
public func url() -> URL? { | ||
return URL(string: baseURL + path) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
|
||
|
||
import Foundation | ||
import Combine | ||
|
||
class Network { | ||
|
||
func request<T: Decodable>(with endPoint: Requestable, dataType: T.Type) | ||
-> AnyPublisher<T, NetworkError> { | ||
|
||
guard let url = endPoint.url() else { | ||
let error = NetworkError.network(description: "Couldn't Create URL") | ||
return Fail(error: error).eraseToAnyPublisher() | ||
} | ||
|
||
var request = URLRequest(url: url) | ||
request.httpBody = nil | ||
request.httpMethod = endPoint.httpMethod.rawValue | ||
|
||
return URLSession.shared.dataTaskPublisher(for: request) | ||
.mapError { error in | ||
.network(description: error.localizedDescription) | ||
} | ||
.flatMap(maxPublishers: .max(1)) { pair in | ||
self.decode(data: pair.data, dataType: T.self) | ||
} | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
func post<T: Encodable> (with endPoint: Requestable, dataType: T) | ||
-> AnyPublisher<Int, NetworkError> { | ||
guard let url = endPoint.url() else { | ||
let error = NetworkError.network(description: "Couldn't Create URL") | ||
return Fail(error: error).eraseToAnyPublisher() | ||
} | ||
|
||
let result = encode(anyData: dataType) | ||
let json: Data | ||
switch result { | ||
case .failure(let error): | ||
return Fail(error: error).eraseToAnyPublisher() | ||
case .success(let data): | ||
json = data | ||
} | ||
|
||
var request = URLRequest(url: url) | ||
request.httpBody = json | ||
request.httpMethod = endPoint.httpMethod.rawValue | ||
request.addValue("application/json", forHTTPHeaderField: "Content-Type") | ||
|
||
if json != nil { | ||
request.setValue(String(json.count), | ||
forHTTPHeaderField: "Content-Length") | ||
} | ||
|
||
return URLSession.shared.dataTaskPublisher(for: request) | ||
.tryMap { data, response -> Int in | ||
guard let httpResponse = response as? HTTPURLResponse else { | ||
throw NetworkError.network(description: "Couldn't Create URL") | ||
} | ||
return httpResponse.statusCode | ||
} | ||
.mapError { error in | ||
NetworkError.network(description: error.localizedDescription) | ||
} | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
func decode<T: Decodable>(data: Data, dataType: T.Type) -> AnyPublisher<T, NetworkError> { | ||
let decoder = JSONDecoder() | ||
decoder.keyDecodingStrategy = .convertFromSnakeCase | ||
|
||
return Just(data) | ||
.decode(type: T.self, decoder: decoder) | ||
.mapError { error in | ||
.parsing(description: error.localizedDescription) | ||
} | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
func encode<T:Encodable>(anyData: T) -> Result<Data,NetworkError> { | ||
let encoder = JSONEncoder() | ||
encoder.outputFormatting = .prettyPrinted | ||
|
||
guard let data = try? encoder.encode(anyData) else { | ||
return Result.failure(NetworkError.encoding(description: "encoding Failure")) | ||
} | ||
return Result.success(data) | ||
} | ||
} | ||
|
||
|
||
enum NetworkError: Error { | ||
case encoding(description: String) | ||
case parsing(description: String) | ||
case network(description: String) | ||
} | ||
|
||
public enum HttpMethod: String { | ||
case get = "GET" | ||
case post = "POST" | ||
} |
25 changes: 25 additions & 0 deletions
25
iOS/Baseball/Baseball/Model/ViewModel/GameListViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// GameListViewModel.swift | ||
// Baseball | ||
// | ||
// Created by 심영민 on 2021/05/06. | ||
// | ||
|
||
import Foundation | ||
|
||
class GameListViewModel { | ||
@Published var gameList: GameList! | ||
private var fetchGameList: FetchGameList | ||
|
||
init(fetchGameList: FetchGameList) { | ||
self.fetchGameList = FetchGameList() | ||
fetchGameListViewModel() | ||
} | ||
|
||
func fetchGameListViewModel() { | ||
fetchGameList.fetchGameList(completion: { result in | ||
self.gameList = result.gameList | ||
}) | ||
} | ||
|
||
} |
Oops, something went wrong.