Skip to content

Si-gongan/pickforme-ios-only

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PickForMe iOS - Standalone Version

Purpose: iOS-only development without backend dependency Architecture: SwiftUI + MVVM + Combine Dependencies: Zero third-party packages Accessibility: VoiceOver-first design


🎯 Why This Version?

This is a standalone iOS project that works with your existing backend without requiring any backend changes. Use this if:

  • ✅ Backend teammate is unavailable
  • ✅ You want to develop iOS independently
  • ✅ Backend is stable and doesn't need changes
  • ✅ You prefer solo development workflow

📁 Project Structure

pickforme-ios-only/
├── pickforme_ios_onlyApp.swift      # App entry point
├── ContentView.swift                 # Main view
│
├── Core/                            # Core infrastructure
│   ├── Networking/
│   │   ├── APIClient.swift          # URLSession wrapper
│   │   ├── APIError.swift           # Error handling
│   │   └── Endpoint.swift           # API endpoints
│   ├── Storage/
│   │   └── KeychainManager.swift   # Secure storage
│   ├── Managers/                    # Coming soon
│   └── Utilities/
│       ├── Constants.swift          # App constants
│       └── Extensions/
│           └── View+Accessibility.swift  # Accessibility helpers
│
├── Features/                        # Feature modules (MVVM)
│   ├── Authentication/
│   │   ├── Models/
│   │   │   └── User.swift          # User model
│   │   ├── ViewModels/             # Coming soon
│   │   └── Views/                  # Coming soon
│   ├── Products/
│   │   ├── Models/
│   │   │   └── Product.swift       # Product model with accessibility
│   │   ├── ViewModels/             # Coming soon
│   │   └── Views/                  # Coming soon
│   ├── AIFeatures/                 # Coming soon
│   ├── Messaging/                  # Coming soon
│   ├── Profile/                    # Coming soon
│   └── Shared/
│       └── Views/
│           ├── LoadingView.swift   # Accessible loading
│           ├── ErrorView.swift     # Accessible error display
│           └── EmptyStateView.swift # Accessible empty states
│
└── Resources/
    └── Assets.xcassets/            # Images, colors

🚀 Quick Start

1. Update Backend URL (1 minute)

Edit Core/Utilities/Constants.swift:

enum API {
    static let baseURL = "https://api.pickforme.com"  // ← Your backend URL
}

2. Build & Run (1 minute)

cd ~/Desktop/pickforme-ios-only
open pickforme-ios-only.xcodeproj

In Xcode:

  • Select iPhone 15 Pro simulator
  • Press Cmd+R to run

3. Test VoiceOver (2 minutes)

  • Enable VoiceOver: Cmd+F5
  • Swipe right/left to navigate
  • Every element should have Korean labels

♿ Accessibility Requirements

CRITICAL: Every user uses VoiceOver!

Every View Must Have:

  1. Accessibility Label (what it is)

    .accessibilityLabel("상품 버튼")
  2. Accessibility Value (current state)

    .accessibilityValue("10,000원")
  3. Accessibility Hint (what happens)

    .accessibilityHint("두 번 탭하여 상세 정보 보기")
  4. Minimum Touch Target (44x44 pt)

    .minimumTouchTarget(width: 44, height: 44)

Testing Checklist:

  • Enable VoiceOver (Cmd+F5)
  • Navigate entire screen
  • All content readable
  • All actions performable
  • Test with largest text size

🔧 Core Features

1. APIClient (Pure URLSession)

// Simple async/await pattern
do {
    let products: ProductListResponse = try await APIClient.shared.request(
        .getProducts(page: 1, limit: 20)
    )
    // Handle success
} catch {
    // Handle error with Korean message
}

Features:

  • Automatic JWT token injection
  • Korean error messages
  • Network error handling
  • No third-party dependencies

2. KeychainManager (Secure Storage)

// Save token
KeychainManager.shared.saveToken("jwt_token_here")

// Get token
if let token = KeychainManager.shared.getToken() {
    // Use token
}

// Delete token (logout)
KeychainManager.shared.deleteToken()

Features:

  • Secure token storage
  • Thread-safe
  • Simple API

3. Accessibility Extensions

Text("상품명")
    .accessibleElement(
        label: "상품명, 가격 10,000원",
        value: "즐겨찾기에 추가됨",
        hint: "두 번 탭하여 상세 정보 보기",
        traits: .isButton
    )

Features:

  • Easy-to-use modifiers
  • Korean labels
  • Dynamic Type support

📋 Development Workflow

Week 1: Authentication

  1. Create LoginView and LoginViewModel
  2. Implement Apple/Google/Kakao Sign In
  3. Save JWT token to Keychain
  4. Test with VoiceOver

Week 2: Product List

  1. Create ProductListViewModel and ProductListView
  2. Fetch products from API
  3. Display in accessible list
  4. Add pull-to-refresh
  5. Test with VoiceOver

Week 3-4: Product Detail & Search

  1. Create ProductDetailView
  2. Implement search
  3. Add favorites
  4. Test with VoiceOver

Week 5+: Additional Features

  1. AI features (report, summary, Q&A)
  2. Messaging
  3. Profile
  4. In-app purchases

🔒 Security Checklist

Never Commit:

  • API keys
  • Firebase config (GoogleService-Info.plist)
  • Certificates (.p8, .p12)
  • Environment files (.env)

Always:

  • Use Keychain for tokens
  • HTTPS only
  • Validate inputs
  • Check .gitignore

🧪 Testing Strategy

VoiceOver Testing (CRITICAL!)

1. Enable VoiceOver: Cmd+F5
2. Close your eyes
3. Navigate using swipe gestures only
4. Can you complete all tasks?
5. Are all labels clear in Korean?

Dynamic Type Testing

1. Settings → Display & Brightness → Text Size
2. Move to maximum
3. Open app
4. All text readable?
5. Buttons still work?

Network Testing

1. Enable Airplane Mode
2. Try to fetch data
3. Clear error message?
4. Retry works?

💡 Key Differences from Team Version

Feature Team Version Standalone Version
Backend Needs coordination Works with existing
Development Two teams iOS only
Backend changes May be needed Not required
Timeline 16 weeks Flexible
Risk Dependency on backend dev Independent

📞 Quick Reference

API Call

let response: T = try await APIClient.shared.request(.endpoint)

Save/Get Token

KeychainManager.shared.saveToken(token)
let token = KeychainManager.shared.getToken()

Accessibility

.accessibilityLabel("레이블")
.accessibilityValue("")
.accessibilityHint("힌트")
.minimumTouchTarget()

ViewModel Pattern

@MainActor
class MyViewModel: ObservableObject {
    @Published var data: [Item] = []
    @Published var isLoading = false

    func fetchData() async {
        isLoading = true
        // Fetch
        isLoading = false
    }
}

🎨 Code Style

Swift

  • Use let over var
  • Prefer guard for early returns
  • Use async/await over closures
  • Explicit self only when required

Naming

  • ViewModels: ProductListViewModel
  • Views: ProductListView
  • Models: Product, User

Accessibility

  • Always Korean labels
  • Brief hints
  • Test with VoiceOver
  • Support Dynamic Type

✅ Pre-Commit Checklist

  • All views have accessibility labels
  • Tested with VoiceOver
  • Tested with largest text
  • No sensitive data
  • Code follows style guide
  • No warnings

🆘 Common Issues

Build Error: "Cannot find 'AppConstants'"

Solution: Check file target membership in File Inspector

VoiceOver Not Reading

Solution: Add explicit .accessibilityLabel()

Text Truncated

Solution: Use .fixedSize(horizontal: false, vertical: true)

Buttons Too Small

Solution: Use .minimumTouchTarget()


📚 Resources

Apple Documentation

Migration Plans (Desktop)

  • IOS_MIGRATION_PLAN.md - Detailed 16-week plan
  • COORDINATION_PLAN.md - Team coordination
  • BACKEND_DEVELOPMENT_PLAN.md - Backend plan

🎯 Success Criteria

You're ready to ship when:

  • ✅ All features working
  • ✅ 100% VoiceOver accessible
  • ✅ Dynamic Type support
  • ✅ No P0/P1 bugs
  • ✅ TestFlight tested
  • ✅ App Store ready

Remember: Every single user uses VoiceOver. Accessibility is not optional - it's THE feature.

Start building! 🚀


Last Updated: November 13, 2025 Status: Foundation Ready ✅

About

기존 서버 체제 유지

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages