diff --git a/Baseball/Baseball.xcodeproj/project.pbxproj b/Baseball/Baseball.xcodeproj/project.pbxproj index a8e2892e9..a6399a58f 100644 --- a/Baseball/Baseball.xcodeproj/project.pbxproj +++ b/Baseball/Baseball.xcodeproj/project.pbxproj @@ -22,6 +22,11 @@ A05951C9264A69F1002B759A /* GameScoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05951C8264A69F1002B759A /* GameScoreViewController.swift */; }; A05951CE264A7921002B759A /* GameScoreTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05951CD264A7921002B759A /* GameScoreTableViewCell.swift */; }; A06524AB2643B7C700CF375D /* PitchHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A06524AA2643B7C700CF375D /* PitchHistoryView.swift */; }; + A0907C2F264BB7F1007ABB1F /* GamePlayRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0907C2E264BB7F1007ABB1F /* GamePlayRepository.swift */; }; + A0907C31264BB8F9007ABB1F /* GamePlayDTO+Mapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0907C30264BB8F9007ABB1F /* GamePlayDTO+Mapping.swift */; }; + A0907C33264BBE70007ABB1F /* GamePlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0907C32264BBE70007ABB1F /* GamePlay.swift */; }; + A0907C35264BC06A007ABB1F /* FetchGamePlayUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0907C34264BC06A007ABB1F /* FetchGamePlayUseCase.swift */; }; + A0907C37264BC1B1007ABB1F /* GamePlayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0907C36264BC1B1007ABB1F /* GamePlayViewModel.swift */; }; A098D28C264383D700950F8F /* GamePlayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A098D28B264383D700950F8F /* GamePlayViewController.swift */; }; A09F9F2C26490CD700A78969 /* FetchGameListUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09F9F2B26490CD700A78969 /* FetchGameListUseCase.swift */; }; A09F9F3126490F4B00A78969 /* GameListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09F9F3026490F4B00A78969 /* GameListRepository.swift */; }; @@ -56,6 +61,11 @@ A05951C8264A69F1002B759A /* GameScoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScoreViewController.swift; sourceTree = "<group>"; }; A05951CD264A7921002B759A /* GameScoreTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScoreTableViewCell.swift; sourceTree = "<group>"; }; A06524AA2643B7C700CF375D /* PitchHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PitchHistoryView.swift; sourceTree = "<group>"; }; + A0907C2E264BB7F1007ABB1F /* GamePlayRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePlayRepository.swift; sourceTree = "<group>"; }; + A0907C30264BB8F9007ABB1F /* GamePlayDTO+Mapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GamePlayDTO+Mapping.swift"; sourceTree = "<group>"; }; + A0907C32264BBE70007ABB1F /* GamePlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePlay.swift; sourceTree = "<group>"; }; + A0907C34264BC06A007ABB1F /* FetchGamePlayUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchGamePlayUseCase.swift; sourceTree = "<group>"; }; + A0907C36264BC1B1007ABB1F /* GamePlayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePlayViewModel.swift; sourceTree = "<group>"; }; A098D28B264383D700950F8F /* GamePlayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePlayViewController.swift; sourceTree = "<group>"; }; A09F9F2B26490CD700A78969 /* FetchGameListUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchGameListUseCase.swift; sourceTree = "<group>"; }; A09F9F3026490F4B00A78969 /* GameListRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameListRepository.swift; sourceTree = "<group>"; }; @@ -184,6 +194,7 @@ A025C3482641160F00C9B8C7 /* ViewModel */ = { isa = PBXGroup; children = ( + A0907C36264BC1B1007ABB1F /* GamePlayViewModel.swift */, ); path = ViewModel; sourceTree = "<group>"; @@ -221,6 +232,7 @@ isa = PBXGroup; children = ( A09F9F2B26490CD700A78969 /* FetchGameListUseCase.swift */, + A0907C34264BC06A007ABB1F /* FetchGamePlayUseCase.swift */, ); path = UseCase; sourceTree = "<group>"; @@ -238,6 +250,7 @@ isa = PBXGroup; children = ( A09F9F3026490F4B00A78969 /* GameListRepository.swift */, + A0907C2E264BB7F1007ABB1F /* GamePlayRepository.swift */, ); path = Repository; sourceTree = "<group>"; @@ -256,6 +269,7 @@ isa = PBXGroup; children = ( A09F9F3726491ECE00A78969 /* GameListDTO+Mapping.swift */, + A0907C30264BB8F9007ABB1F /* GamePlayDTO+Mapping.swift */, ); path = DataMapping; sourceTree = "<group>"; @@ -300,6 +314,7 @@ isa = PBXGroup; children = ( FFDD3A8F264138800037622A /* MatchUp.swift */, + A0907C32264BBE70007ABB1F /* GamePlay.swift */, ); path = Entity; sourceTree = "<group>"; @@ -376,6 +391,8 @@ buildActionMask = 2147483647; files = ( A05951CE264A7921002B759A /* GameScoreTableViewCell.swift in Sources */, + A0907C2F264BB7F1007ABB1F /* GamePlayRepository.swift in Sources */, + A0907C37264BC1B1007ABB1F /* GamePlayViewModel.swift in Sources */, FF57667E2649324200F46A43 /* Alertable.swift in Sources */, FFDD3A92264138F40037622A /* GameListViewModel.swift in Sources */, FFDD3A90264138800037622A /* MatchUp.swift in Sources */, @@ -387,6 +404,7 @@ A05951C1264A27FC002B759A /* BaseballSceneDIContainer.swift in Sources */, A09F9F3826491ECE00A78969 /* GameListDTO+Mapping.swift in Sources */, A025C34C2641164000C9B8C7 /* GroundView.swift in Sources */, + A0907C33264BBE70007ABB1F /* GamePlay.swift in Sources */, A09F9F2C26490CD700A78969 /* FetchGameListUseCase.swift in Sources */, A025C32A2640E8E700C9B8C7 /* AppDelegate.swift in Sources */, A05951C3264A2AB5002B759A /* AppFlowCoordinator.swift in Sources */, @@ -399,7 +417,9 @@ FFDD3A9E2643C3960037622A /* PitchHistoryCell.swift in Sources */, A05951BF264A27EC002B759A /* AppDIContainer.swift in Sources */, FFDD3AA62644FD9B0037622A /* CALayer+Extension.swift in Sources */, + A0907C35264BC06A007ABB1F /* FetchGamePlayUseCase.swift in Sources */, A09F9F3126490F4B00A78969 /* GameListRepository.swift in Sources */, + A0907C31264BB8F9007ABB1F /* GamePlayDTO+Mapping.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Baseball/Baseball/Application/DIContainer/BaseballSceneDIContainer.swift b/Baseball/Baseball/Application/DIContainer/BaseballSceneDIContainer.swift index b64d7ea16..bca3a4ee1 100644 --- a/Baseball/Baseball/Application/DIContainer/BaseballSceneDIContainer.swift +++ b/Baseball/Baseball/Application/DIContainer/BaseballSceneDIContainer.swift @@ -18,6 +18,7 @@ class BaseballSceneDIContainer: BaseballFlowCoordinatorDependencies { self.dependencies = dependencies } + //MARK: - GameListView private func makeGameListRepository() -> GameListRepository { return DefaultGameListRepository(networkService: dependencies.apiNetwork) } @@ -26,14 +27,32 @@ class BaseballSceneDIContainer: BaseballFlowCoordinatorDependencies { return DefaultFetchGameListUseCase(gameListRepository: makeGameListRepository()) } - private func makeGameListViewModel() -> GameListViewModel { - return GameListViewModel(fetchGameListUseCase: makeFetchGameListUseCase()) + private func makeGameListViewModel(action: GameListViewModelAction) -> GameListViewModel { + return GameListViewModel(fetchGameListUseCase: makeFetchGameListUseCase(), action: action) } - func makeGameListViewController() -> GameListViewController { - return GameListViewController.create(with: makeGameListViewModel()) + func makeGameListViewController(action: GameListViewModelAction) -> GameListViewController { + return GameListViewController.create(with: makeGameListViewModel(action: action)) } + //MARK: - GamePlayView + private func makeGamePlayRepository() -> GamePlayRepository { + return DefaultGamePlayRepository(networkService: dependencies.apiNetwork) + } + + private func makeFetchGamePlayUseCase() -> FetchGamePlayUseCase { + return DefaultFetchGamePlayUseCase(gamePlayRepository: makeGamePlayRepository()) + } + + private func makeGamePlayViewModel(matchId: Int) -> GamePlayViewModel { + return GamePlayViewModel(matchId: matchId, fetchGamePlayUseCase: makeFetchGamePlayUseCase()) + } + + func makeGamePlayViewController(matchId: Int) -> GamePlayViewController { + return GamePlayViewController.create(with: makeGamePlayViewModel(matchId: matchId)) + } + + //MARK: - Coordinator func makeBaseballSceneCoordinator(navigationController: UINavigationController) -> BaseballSceneFlowCoordinator { return BaseballSceneFlowCoordinator(navigationController: navigationController, dependencies: self) } diff --git a/Baseball/Baseball/Data/Network/DataMapping/GamePlayDTO+Mapping.swift b/Baseball/Baseball/Data/Network/DataMapping/GamePlayDTO+Mapping.swift new file mode 100644 index 000000000..75f073eff --- /dev/null +++ b/Baseball/Baseball/Data/Network/DataMapping/GamePlayDTO+Mapping.swift @@ -0,0 +1,50 @@ +// +// GamePlayDTO+Mapping.swift +// Baseball +// +// Created by Jun Ho JANG on 2021/05/12. +// + +import Foundation + +/* + {"matchId":13, + "away":"awayteam to string", + "home":"hometeam to string", + "inning":1, + "offenseTeam":"offenseTeam to String" + "firstBase":[], + "secondBase":[], + "thirdBase":[], + "pitcher":"kim", + "batter":"dong", + "strike":0, + "ball":0, + "out":0, + "homePoint":0, + "awayPoint":0} + */ + + + +struct GamePlayDTO: Decodable { + private let matchId: Int + private let away: String + private let home: String + private let inning: Int + private let offenseTeam: String + private let firstBase: [String] + private let secondBase: [String] + private let thirdBase: [String] + private let pitcher: String + private let batter: String + private let strike: Int + private let ball: Int + private let out: Int + private let homePoint: Int + private let awayPoint: Int + + func toDomain() -> GamePlay { + return .init(matchId: matchId, away: away, home: home, inning: inning, offenseTeam: offenseTeam, firstBase: firstBase, secondBase: secondBase, thirdBase: thirdBase, pitcher: pitcher, batter: batter, strike: strike, ball: ball, out: out, homePoint: homePoint, awayPoint: awayPoint) + } +} diff --git a/Baseball/Baseball/Data/Network/NetworkEndpoint.swift b/Baseball/Baseball/Data/Network/NetworkEndpoint.swift index 1f81a8e02..d24f46573 100644 --- a/Baseball/Baseball/Data/Network/NetworkEndpoint.swift +++ b/Baseball/Baseball/Data/Network/NetworkEndpoint.swift @@ -29,6 +29,21 @@ struct GameListEndpoint: Requestable { } } +struct GamePlayEndPoint: Requestable { + var baseUrl = "http://3.35.226.74/games/offense/" + var path: String + var httpMethod: HTTPMethod + + init(httpMethod: HTTPMethod, path: String) { + self.httpMethod = httpMethod + self.path = path + } + + func url() -> URL? { + return URL(string: baseUrl + path) + } +} + enum HTTPMethod: String { case get = "GET" case post = "POST" diff --git a/Baseball/Baseball/Data/Repository/GamePlayRepository.swift b/Baseball/Baseball/Data/Repository/GamePlayRepository.swift new file mode 100644 index 000000000..57a3b8f8e --- /dev/null +++ b/Baseball/Baseball/Data/Repository/GamePlayRepository.swift @@ -0,0 +1,42 @@ +// +// GamePlayRepository.swift +// Baseball +// +// Created by Jun Ho JANG on 2021/05/12. +// + +import Foundation +import Combine + +protocol GamePlayRepository { + func fetchGamePlayData(matchId: Int, completion: @escaping (Result<GamePlay, NetworkError>) -> Void) +} + +class DefaultGamePlayRepository: GamePlayRepository { + + private let networkService: NetworkService + private var subscriptions = Set<AnyCancellable>() + + init(networkService: NetworkService) { + self.networkService = networkService + } + + func fetchGamePlayData(matchId: Int, completion: @escaping (Result<GamePlay, NetworkError>) -> Void) { + let path = String(matchId) + let endpoint = GamePlayEndPoint(httpMethod: .get, path: path) + + self.networkService.request(with: endpoint, dataType: GamePlayDTO.self) + .sink { result in + switch result { + case .failure(let error): + completion(.failure(error)) + case .finished: + break + } + } receiveValue: { gamePlayDTO in + let gamePlayData = gamePlayDTO.toDomain() + completion(.success(gamePlayData)) + } + .store(in: &self.subscriptions) + } +} diff --git a/Baseball/Baseball/Domain/Entity/GamePlay.swift b/Baseball/Baseball/Domain/Entity/GamePlay.swift new file mode 100644 index 000000000..a772c4019 --- /dev/null +++ b/Baseball/Baseball/Domain/Entity/GamePlay.swift @@ -0,0 +1,26 @@ +// +// GamePlay.swift +// Baseball +// +// Created by Jun Ho JANG on 2021/05/12. +// + +import Foundation + +struct GamePlay { + var matchId: Int + var away: String + var home: String + var inning: Int + var offenseTeam: String + var firstBase: [String] + var secondBase: [String] + var thirdBase: [String] + var pitcher: String + var batter: String + var strike: Int + var ball: Int + var out: Int + var homePoint: Int + var awayPoint: Int +} diff --git a/Baseball/Baseball/Domain/UseCase/FetchGamePlayUseCase.swift b/Baseball/Baseball/Domain/UseCase/FetchGamePlayUseCase.swift new file mode 100644 index 000000000..26faae0d7 --- /dev/null +++ b/Baseball/Baseball/Domain/UseCase/FetchGamePlayUseCase.swift @@ -0,0 +1,26 @@ +// +// FetchGamePlayUseCase.swift +// Baseball +// +// Created by Jun Ho JANG on 2021/05/12. +// + +import Foundation + +protocol FetchGamePlayUseCase { + func execute(matchId: Int, completion: @escaping(Result<GamePlay,NetworkError>) -> Void) +} + +class DefaultFetchGamePlayUseCase: FetchGamePlayUseCase { + private let gamePlayRepository: GamePlayRepository + + init(gamePlayRepository: GamePlayRepository) { + self.gamePlayRepository = gamePlayRepository + } + + func execute(matchId : Int, completion: @escaping (Result<GamePlay,NetworkError>) -> Void) { + gamePlayRepository.fetchGamePlayData(matchId: matchId) { result in + completion(result) + } + } +} diff --git a/Baseball/Baseball/Presentation/Flow/BaseballSceneFlowCoordinator.swift b/Baseball/Baseball/Presentation/Flow/BaseballSceneFlowCoordinator.swift index 8e5645aed..a4c53836b 100644 --- a/Baseball/Baseball/Presentation/Flow/BaseballSceneFlowCoordinator.swift +++ b/Baseball/Baseball/Presentation/Flow/BaseballSceneFlowCoordinator.swift @@ -8,7 +8,8 @@ import UIKit protocol BaseballFlowCoordinatorDependencies { - func makeGameListViewController() -> GameListViewController + func makeGameListViewController(action: GameListViewModelAction) -> GameListViewController + func makeGamePlayViewController(matchId: Int) -> GamePlayViewController } class BaseballSceneFlowCoordinator { @@ -22,8 +23,15 @@ class BaseballSceneFlowCoordinator { } func start() { - let vc = dependencies.makeGameListViewController() + let action = GameListViewModelAction(showGamePlayView: showGamePlayView(matchUp:)) + let vc = dependencies.makeGameListViewController(action: action) navigationController?.pushViewController(vc, animated: true) gameListVC = vc } + + // let showGamePlayView: ((Int)-> Void) + func showGamePlayView(matchUp: Int) { + let vc = dependencies.makeGamePlayViewController(matchId: matchUp) + self.navigationController?.pushViewController(vc, animated: true) + } } diff --git a/Baseball/Baseball/Presentation/GameListView/View/GameListViewController.swift b/Baseball/Baseball/Presentation/GameListView/View/GameListViewController.swift index 53fd735cd..2fffbf90d 100644 --- a/Baseball/Baseball/Presentation/GameListView/View/GameListViewController.swift +++ b/Baseball/Baseball/Presentation/GameListView/View/GameListViewController.swift @@ -81,6 +81,12 @@ extension GameListViewController: UICollectionViewDataSource { } } +extension GameListViewController: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + viewModel.didSelectItem(indexPath: indexPath) + } +} + extension GameListViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 40 diff --git a/Baseball/Baseball/Presentation/GameListView/ViewModel/GameListViewModel.swift b/Baseball/Baseball/Presentation/GameListView/ViewModel/GameListViewModel.swift index 5f2b2a535..37698b8c9 100644 --- a/Baseball/Baseball/Presentation/GameListView/ViewModel/GameListViewModel.swift +++ b/Baseball/Baseball/Presentation/GameListView/ViewModel/GameListViewModel.swift @@ -8,17 +8,23 @@ import Foundation import Combine +struct GameListViewModelAction { + typealias MatchUpID = Int + let showGamePlayView: ((MatchUpID) -> Void) +} + class GameListViewModel { @Published private (set) var matchUpGames: [MatchUp] @Published private (set) var error: String private var fetchGameListUseCase: FetchGameListUseCase + private var action: GameListViewModelAction - init(fetchGameListUseCase: FetchGameListUseCase) { + init(fetchGameListUseCase: FetchGameListUseCase, action: GameListViewModelAction) { self.matchUpGames = [] self.error = "" self.fetchGameListUseCase = fetchGameListUseCase - + self.action = action fetchGameList() } @@ -41,4 +47,8 @@ class GameListViewModel { self.error = des } } + + func didSelectItem(indexPath: IndexPath) { + action.showGamePlayView(indexPath.item + 1) + } } diff --git a/Baseball/Baseball/Presentation/GamePlayView/View/GamePlayViewController.swift b/Baseball/Baseball/Presentation/GamePlayView/View/GamePlayViewController.swift index e09632ab4..84ac6fdab 100644 --- a/Baseball/Baseball/Presentation/GamePlayView/View/GamePlayViewController.swift +++ b/Baseball/Baseball/Presentation/GamePlayView/View/GamePlayViewController.swift @@ -6,18 +6,32 @@ // import UIKit +import Combine class GamePlayViewController: UIViewController { @IBOutlet weak var groundView: GroundView! @IBOutlet weak var pitchHistoryTableView: UITableView! @IBOutlet weak var pitcherView: UIView! - + // 홈 1루 2루 3루 private var runners: [RunnerView?] = [nil, nil, nil, nil] private var animator: UIViewPropertyAnimator? private var basePoint: [CGPoint]? + private var viewModel: GamePlayViewModel! + private var subscriptions = Set<AnyCancellable>() + + static let storyboardName = "Main" + static let storyboardID = "GamePlayViewController" + static func create(with viewModel: GamePlayViewModel) -> GamePlayViewController { + let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main) + guard let vc = storyboard.instantiateViewController(identifier: storyboardID) as? GamePlayViewController else { + return GamePlayViewController() + } + vc.viewModel = viewModel + return vc + } override func viewDidLoad() { super.viewDidLoad() diff --git a/Baseball/Baseball/Presentation/GamePlayView/ViewModel/GamePlayViewModel.swift b/Baseball/Baseball/Presentation/GamePlayView/ViewModel/GamePlayViewModel.swift new file mode 100644 index 000000000..8be001c91 --- /dev/null +++ b/Baseball/Baseball/Presentation/GamePlayView/ViewModel/GamePlayViewModel.swift @@ -0,0 +1,45 @@ +// +// GamePlayViewModel.swift +// Baseball +// +// Created by Jun Ho JANG on 2021/05/12. +// + +import Foundation +import Combine + +class GamePlayViewModel { + @Published private (set) var gamePlay: GamePlay! + @Published private (set) var error: String + + private var fetchGamePlayUseCase: FetchGamePlayUseCase + private var matchId: Int + + init(matchId: Int, fetchGamePlayUseCase: FetchGamePlayUseCase) { + self.matchId = matchId + self.error = "" + self.fetchGamePlayUseCase = fetchGamePlayUseCase + fetchGamePlay() + } + + func fetchGamePlay() { + fetchGamePlayUseCase.execute(matchId: matchId) { result in + switch result { + case .success(let gamePlay): + self.gamePlay = gamePlay + print(result) + case .failure(let error): + self.errorHandler(error: error) + } + } + } + + private func errorHandler(error: NetworkError) { + switch error { + case .network(description: let des): + self.error = des + case .parsing(description: let des): + self.error = des + } + } +} diff --git a/Baseball/Baseball/SupportingFile/Base.lproj/Main.storyboard b/Baseball/Baseball/SupportingFile/Base.lproj/Main.storyboard index 46d1db922..90b7a02b4 100644 --- a/Baseball/Baseball/SupportingFile/Base.lproj/Main.storyboard +++ b/Baseball/Baseball/SupportingFile/Base.lproj/Main.storyboard @@ -142,7 +142,7 @@ <!--Item--> <scene sceneID="ilJ-Q9-AXy"> <objects> - <viewController id="kzF-gc-ebD" customClass="GamePlayViewController" customModule="Baseball" customModuleProvider="target" sceneMemberID="viewController"> + <viewController storyboardIdentifier="GamePlayViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="kzF-gc-ebD" customClass="GamePlayViewController" customModule="Baseball" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="Bse-3r-WIJ"> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> @@ -345,7 +345,7 @@ <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bcQ-FI-LkX" customClass="PaddingLabel" customModule="Baseball" customModuleProvider="target"> - <rect key="frame" x="8" y="14" width="6.5" height="16"/> + <rect key="frame" x="8" y="11" width="20.5" height="22"/> <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <fontDescription key="fontDescription" type="system" weight="medium" pointSize="13"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> @@ -368,7 +368,7 @@ </userDefinedRuntimeAttributes> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="스트라이크" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t4x-ed-cTS"> - <rect key="frame" x="24.5" y="7.5" width="104" height="29"/> + <rect key="frame" x="38.5" y="7.5" width="104" height="29"/> <fontDescription key="fontDescription" type="system" weight="medium" pointSize="24"/> <nil key="textColor"/> <nil key="highlightedColor"/> @@ -832,7 +832,7 @@ </scenes> <designables> <designable name="bcQ-FI-LkX"> - <size key="intrinsicContentSize" width="6.5" height="16"/> + <size key="intrinsicContentSize" width="20.5" height="22"/> </designable> </designables> <resources>