Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,11 @@
/* Begin PBXFileReference section */
0453294E2C5B8E3400BBE289 /* Climeet-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Climeet-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
0489EEF92C3BE58E00BFC55B /* Climeet-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Climeet-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
04ED90052CD3A519009B59A0 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
B94EC2222BD13CBB00DC3FDB /* Climeet-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Climeet-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
B94EC2412BD1473E00DC3FDB /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
041DA0422CF419B600CFDC31 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Debug.xcconfig,
Shared.xcconfig,
);
target = B94EC2212BD13CBB00DC3FDB /* Climeet-iOS */;
};
604B97A62CC394F2005EDD29 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Expand All @@ -60,7 +51,7 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
604B958E2CC394EF005EDD29 /* XCConfig */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (041DA0422CF419B600CFDC31 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = XCConfig; sourceTree = "<group>"; };
604B958E2CC394EF005EDD29 /* XCConfig */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = XCConfig; sourceTree = "<group>"; };
604B96BF2CC394F2005EDD29 /* Climeet-iOS */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (604B97A62CC394F2005EDD29 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOS"; sourceTree = "<group>"; };
604B97A82CC394F5005EDD29 /* Climeet-iOSTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOSTests"; sourceTree = "<group>"; };
604B97AC2CC394F7005EDD29 /* Climeet-iOSUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOSUITests"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -208,7 +199,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1530;
LastUpgradeCheck = 1600;
LastUpgradeCheck = 1610;
TargetAttributes = {
0453294D2C5B8E3400BBE289 = {
CreatedOnToolsVersion = 15.3;
Expand Down Expand Up @@ -336,8 +327,6 @@
/* Begin XCBuildConfiguration section */
045329572C5B8E3400BBE289 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -382,8 +371,6 @@
};
0489EF002C3BE58E00BFC55B /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
Expand Down Expand Up @@ -430,6 +417,8 @@
};
B94EC22E2BD13CBD00DC3FDB /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
Expand Down Expand Up @@ -493,6 +482,8 @@
};
B94EC22F2BD13CBD00DC3FDB /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
Expand Down Expand Up @@ -550,15 +541,15 @@
B94EC2312BD13CBD00DC3FDB /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\"";
DEVELOPMENT_TEAM = 7MJ69FU8BU;
DEVELOPMENT_TEAM = MV89SHQKF4;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -586,15 +577,16 @@
};
B94EC2322BD13CBD00DC3FDB /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 04ED90052CD3A519009B59A0 /* Release.xcconfig */;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\"";
DEVELOPMENT_TEAM = 7MJ69FU8BU;
DEVELOPMENT_TEAM = MV89SHQKF4;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ struct BannerReducer {

case .timerTick:
state.timerCount += 1
print(state.timerCount)
if state.timerCount == bannerChangeTime {
state.timerCount = 0
// TODO: banner change
Expand Down
5 changes: 5 additions & 0 deletions Climeet-iOS/Climeet-iOS/Presentation/Home/HomeReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ struct HomeReducer {
var banner = BannerReducer.State()
var shortcut = HomeGymShortcutReducer.State()
var bestClimber = HomeBestClimberReducer.State()
var popularShorts = WeeklyPopularShortsReducer.State()
}

enum Action {
case banner(BannerReducer.Action)
case shortcut(HomeGymShortcutReducer.Action)
case bestClimber(HomeBestClimberReducer.Action)
case popularShorts(WeeklyPopularShortsReducer.Action)
}

var body: some ReducerOf<Self> {
Expand All @@ -33,5 +35,8 @@ struct HomeReducer {
Scope(state: \.bestClimber, action: \.bestClimber) {
HomeBestClimberReducer()
}
Scope(state: \.popularShorts, action: \.popularShorts) {
WeeklyPopularShortsReducer()
}
}
}
2 changes: 1 addition & 1 deletion Climeet-iOS/Climeet-iOS/Presentation/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct HomeView: View {
.padding(.bottom, 48)
HomeBestClimberView(store: store.scope(state: \.bestClimber, action: \.bestClimber))
.padding(.bottom, 48)
WeeklyPopularShortsView()
WeeklyPopularShortsView(store: store.scope(state: \.popularShorts, action: \.popularShorts))
.padding(.bottom, 48)
WeeklyPopularGymView()
.padding(.bottom, 48)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// GymDifficulty.swift
// Climeet-iOS
//
// Created by 권승용 on 11/29/24.
//

import Foundation

struct GymDifficulty: Equatable {
let level: Int
let color: String

init(from dto: DifficultyMappingDTO.GymDifficulty.ResponseElement) throws {
guard let level = dto.difficulty,
let color = dto.gymDifficultyColor else {
throw AppError.dataParsingError("dto property nil")
}
self.level = level
self.color = color
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// PopularShorts.swift
// Climeet-iOS
//
// Created by 권승용 on 11/29/24.
//

import Foundation

struct PopularShorts: Equatable, Identifiable {
let id = UUID()
let gymName: String
let thumbnailImageURL: String
let difficulty: GymDifficulty

init(from dto: ShortsDTO.Shorts.Response, difficulty: GymDifficulty) throws {
guard let gymName = dto.gymName,
let thumbnailImageURL = dto.thumbnailImageURL else {
throw AppError.dataParsingError("dto property nil")
}
self.gymName = gymName
self.thumbnailImageURL = thumbnailImageURL
self.difficulty = difficulty
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// WeeklyPopularShortsReducer.swift
// Climeet-iOS
//
// Created by 권승용 on 11/26/24.
//

import Foundation
import ComposableArchitecture

@Reducer
struct WeeklyPopularShortsReducer {
@ObservableState
struct State: Equatable {
var shortsItems: IdentifiedArrayOf<PopularShorts> = []
}

enum Action {
case onFirstAppear
case popularShortsResponse([PopularShorts])
}

@Dependency(\.shortsClient) var shortsClient
@Dependency(\.difficultyMappingClient) var difficultyMappingClient

var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .onFirstAppear:
return .run { send in
let request = ShortsDTO.List.Request(page: 0, size: 10)
let response = try await shortsClient.popularShorts(request)

let result = try await withThrowingTaskGroup(of: PopularShorts?.self) { group in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withThrowingTaskGroup 쓰신 이유가 무엇일까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 개의 비동기 작업을 concurrent하게 처리하기 위함입니다.
반복문 안에 await을 사용할 시 해당 작업이 끝난 후 다음 반복문이 serial하게 수행됩니다.
이를 concurrent하게 수행하고 싶어 사용해 보았습니다~

Copy link
Contributor

@HenryVoid HenryVoid Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 파악하고 있는게 맞는지 확인 부탁드려도 될까요?!
이번주 인기숏츠영상별 뱃지를 표현하기 위해 gymDifficulty API를 반복해서 호출하는 것으로 보이는데 성능저하, 즉 네트워킹환경에 따라서 무기한 대기상황을 초래할 수도 있다 생각되서요! 그래서 찾아보니 popularShorts API Response에 gymDifficultyName, gymDifficultyColor가 존재하는데 이것으로는 해결이 안 되는 것일까요?!

스크린샷 2025-01-01 오후 5 54 43

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 각 난이도에 따른 레벨 표시(V1, V3 등) 값을 알기 위해 추가적인 API 호출이 필요한 상황입니다..!
형욱님이 알려주신 부분은 쇼츠 썸네일 정보를 위해 과다한 API 호출이 이루어진다는 점인 것으로 이해됩니다.
그 부분 저도 동의하고 있습니다~ API 호출을 최대한 줄이고 싶은데, 현재 쇼츠 API 구성의 한계로 인해 이렇게 구현하였습니다 ㅜㅜ
혹시 더 좋은 방법이 있을까요?

for responseItem in response.result {
group.addTask {
guard let id = responseItem.shortsDetailInfo?.gymID else {
throw AppError.dataParsingError("gymID not found")
}

let difficulty = try await difficultyMappingClient.gymDifficulty(id)

guard !difficulty.isEmpty else { return nil }

return try PopularShorts(
from: responseItem,
difficulty: try GymDifficulty(from: difficulty[0])
)
}
}

var popularShorts: [PopularShorts] = []

for try await item in group {
if let item = item {
popularShorts.append(item)
}
}

return popularShorts
}

await send(.popularShortsResponse(result))
}

case let .popularShortsResponse(response):
state.shortsItems = IdentifiedArray(uniqueElements: response)
print(state.shortsItems)
return .none
}
}
}
}
Loading