8000 GitHub - yildizkoray/armony-ios
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

yildizkoray/armony-ios

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Armony iOS

Armony helps musicians connect with each other. Users can create profiles showing their musical skills and find other musicians to work with. It's perfect for musicians, songwriters, composers, sound engineers, music teachers, producers, and more. You can find it on the App Store or visit Armony for more info.

Screenshots

Table of Contents

Project Tech Stack

  • Language: Swift
  • UI Frameworks: UIKit & SwiftUI
  • Minimum iOS Version: 15.0
  • Design Pattern: MVVM-C
  • Package Manager: Swift Package Manager
  • Main Libraries: Alamofire, AlamofireImage and UIScrollView-InfiniteScroll
  • Style Guide: Raywenderlich
  • Powered by ❤️

Getting Started

Follow these steps to get started with the project:

Prerequisites

  • Xcode
  • Access to Firebase and Facebook Developer accounts (to generate required secret keys)

Installation

Clone the repository:

git clone git@github.com:studiogo-armony/armony-ios.git
cd armony-ios

Secrets

This project uses sensitive keys for integrations.

Required Keys

Google Configuration Files

  • GoogleService-Info.plist: For Release builds
  • GoogleService-Info-Debug.plist: For Debug builds

Facebook Keys

  • FACEBOOK_APP_ID
  • FACEBOOK_CLIENT_TOKEN

Mixpanel Keys

  • MIXPANEL_TOKEN

Adjust Keys

  • ADJUST_TOKEN

Managing Secrets

Store secrets in configuration files specific to your environment:

  • Debug Configuration (${PROJECT_DIR}/Armony/Resources/Configs/DebugConfiguration.xcconfig)
  • Release Configuration (${PROJECT_DIR}/Armony/Resources/Configs/ReleaseConfiguration.xcconfig)

Structure

⊢ Common
  ⊢ UI
      ⊢ Analytics
      ⊢ Deeplink
      ⊢ Protocols
      ⊢ UI
        ⊢ Banner, Card, Avatar etc
⊢ Service
    ⊢ Firebase
    ⊢ RemoteNotification
    ⊢ Socket
    ⊢ Authentication
⊢ Scenes
  ⊢ Adverts
    ⊢ API
      ⊢ Tasks // Tasks that retrieve any related response coming from API.
    ⊢ Models // Entity for API
    ⊢ UI
        ⊢ Presentation
        ⊢ View
            ⊢ ABCPresentation.swift //Presentation/ViewModel object of ABC
            ⊢ ABCView.swift
            ⊢ ABCView.xib
    ⊢ AdvertsCoordinator.swift
    ⊢ AdvertsViewModel.swift
    ⊢ AdvertsViewController.swift
    ⊢ Home.storyboard

SwiftUI Integration

This app uses both UIKit and SwiftUI. Here's how we use SwiftUI:

SwiftUI Screens

  • Regions Screen: A screen for selecting regions, built with SwiftUI components
  • AdvertListing Screen: Shows ads in a grid layout
  • Info View: A simple view to show information with an icon

UIKit-SwiftUI Bridge Components

We use these components to connect UIKit and SwiftUI:

  • EmptyStateSwiftUIView: Shows empty states
  • SwiftUICardView: Shows cards
  • NotchViewSwiftUI: Shows the notch view
  • PolicyTextView: Shows text content

Implementation Details

  • Uses MVVM pattern with SwiftUI's @ObservedObject
  • Works with our app's theme system
  • Combines UIKit and SwiftUI views
  • Needs iOS 16+ for some features
  • New screens use SwiftUI
  • Old UIKit components work with SwiftUI

Coordinator Pattern with SwiftUI

We use MVVM-C pattern to handle navigation in both UIKit and SwiftUI screens.

SwiftUI Coordinator Integration

public typealias Navigator = UINavigationController

public protocol Coordinator {
    associatedtype Controller: ViewController
    var navigator
8000
: Navigator? { get }
    
    func createViewController() -> Controller
    func createNavigatorWithRootViewController() -> (navigator: Navigator, view: Controller)
}

protocol SwiftUICoordinator: Coordinator {
    associatedtype Content: View
}

Implementation Example

final class MyCoordinator: SwiftUICoordinator {
    var navigator: Navigator?
    
    typealias Content = MySwiftUIView
    typealias Controller = UIHostingController<MySwiftUIView>
    
    init(navigator: Navigator? = nil) {
        self.navigator = navigator
    }
    
    func start() {
        let viewModel = MySwiftUIViewModel()
        viewModel.coordinator = self
        let view = MySwiftUIView(viewModel: viewModel)
        let hosting = createHostingViewController(rootView: view)
        hosting.title = "TITLE"
        navigator?.pushViewController(hosting, animated: true)
    }
}

With this setup, SwiftUI views:

  • Work with UIKit navigation
  • Use the same navigation system
  • Support deep linking
  • Match the app's style

Deep Linking

Our app uses deep links to open specific screens directly. It's built with a custom URL system.

Deep Link Structure

public extension Deeplink {
    static let account: Deeplink = "/account"
    static let advert: Deeplink = "/advert"
    static let chats: Deeplink = "/chats"
    static let liveChat: Deeplink = "/live-chat"
    // ... and more
}

Key Components

URLNavigator

  • Controls all deep link navigation
  • Handles URL patterns
  • Checks if user is logged in
  • Works with coordinators
  • Can pass data through URLs

URLNavigatable Protocol

public protocol URLNavigatable {
    var isAuthenticationRequired: Bool { get }
    static var instance: URLNavigatable { get }
    static func register(navigator: URLNavigation)
}

Implementation Example

Here's how to add deep linking to a coordinator:

extension MyCoordinator: URLNavigatable {
    var isAuthenticationRequired: Bool { true }
    
    static var instance: URLNavigatable {
        return MyCoordinator()
    }
    
    static func register(navigator: URLNavigation) {
        navigator.register(coordinator: instance, pattern: .myScreen) { result in
        if let id = result.value(forKey: "id") as? String {
            MyCoordinator(navigator: result.navigator, id: id).start()
        }
    }
}

GitHub Actions Scripts

Our project uses GitHub Actions for automated workflows. Here are the main workflows:

Create Release Branch

This workflow automates the creation of release branches with version increments:

# Triggered manually with version type choice
- Automatically increments version (major, minor, or patch)
- Creates a new release branch from development
- Updates the marketing version in Xcode project

Merge Release to Main

This workflow handles merging release branches to the main branch:

# Can be triggered manually or automatically
- Merges the latest release branch to main
- Supports manual selection of release branch
- Uses no-fast-forward merge strategy

Merge Main to Development

This workflow keeps the development branch in sync with main:

# Triggers:
- Automatically after successful release merge
- Manually when needed
- Ensures development branch stays updated with main

CI Scripts

Our project includes several CI scripts in the ci_scripts directory that handle different stages of the build process. These scripts are designed to work with both Xcode Cloud and other CI environments.

Pre-Xcodebuild Script

ci_pre_xcodebuild.sh runs before the build process starts:

# Main responsibilities:
- Validates required environment variables
- Sets up configuration files for different environments (Debug/Release)
- Configures third-party service integrations
- Updates necessary plists and configuration files

Post-Clone Script

ci_post_clone.sh runs after repository cloning:

# Main responsibilities:
- Creates necessary directory structure
- Sets up configuration files
- Initializes required plists
- Prepares the environment for building

Post-Xcodebuild Script

ci_post_xcodebuild.sh runs after the build process:

# Main responsibilities:
- Handles debug symbol uploads
- Processes build artifacts
- Performs necessary post-build tasks

Networking

Our project uses a layered networking architecture that provides type-safe API requests. Here's how it works:

RestService

The core service class that handles all network operations:

class RestService: Service {
    func execute<R: APIResponse>(task: HTTPTask, type: R.Type) async throws -> R
}
673F

Response Types

  • RestObjectResponse<T>: For single object responses
  • RestArrayResponse<T>: For array responses
  • Built-in error handling with RestErrorResponse

HTTPTask Protocol

Each API endpoint is represented by a task that implements HTTPTask:

struct GetMyNetworkTask: HTTPTask {
    var method: HTTPMethod = .get
    var path: String = "/my-network"
    var urlQueryItems: [URLQueryItem]?
    
    init(userID: String) {
        urlQueryItems = [
            URLQueryItem(name: "userID", value: userID)
        ]
    }
}

Usage Example

// Create the task
let task = GetMyNetworkTask(userID: "123")

// Execute the request
Task { 
    do {
        let response = try await restService.execute(
            task: task, 
            type: RestArrayResponse<MyNetworkModel>.self
        )
        // Handle response
    } catch {
        // Handle error
    }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 98.8%
  • Shell 1.2%
0