@datacomvn/lunar-date-picker
Version:
A powerful React Native lunar date picker with timezone support, lazy loading, and native performance built on Nitro Modules
165 lines (135 loc) • 5.78 kB
Markdown
# iOS Lunar Date Picker
A professionally architected iOS implementation of the Lunar Date Picker for React Native Nitro Module.
## Architecture Overview
The iOS implementation follows clean architecture principles with clear separation of concerns:
```
ios/
├── LunarDatePicker.swift # Main entry point for React Native bridge
├── coordinators/ # Coordinators for managing flow
│ └── LunarDatePickerCoordinator.swift
├── services/ # Business logic services
│ ├── ConfigurationBuilder.swift # Builds picker configurations
│ └── PickerPresenter.swift # Handles picker presentation
├── factories/ # Factory pattern implementations
│ └── PickerControllerFactory.swift
├── protocols/ # Protocol definitions
│ ├── ConfigurationProviding.swift
│ └── PickerPresenting.swift
├── views/ # UI components
│ ├── PickerController.swift # Main picker view controller
│ ├── PickerController+CalendarDelegate.swift
│ ├── DayCell.swift # Calendar day cell
│ ├── WeekView.swift # Week header view
│ └── MonthHeader.swift # Month header view
├── models/ # Data models
│ ├── PickerConfig.swift # Configuration model
│ ├── Value.swift # Value types (Date/Range)
│ ├── ColorWrapper.swift # Color handling
│ └── LunarDate.swift # Lunar date model
├── utils/ # Utility classes
│ ├── DateConverter.swift # Date conversion utilities
│ ├── LunarDateUtil.swift # Lunar calendar calculations
│ ├── CalendarConfigurationManager.swift
│ └── Constants.swift # App constants
└── extensions/ # Swift extensions
├── Date+Utilities.swift
├── Calendar+LastWeekday.swift
└── String+CapitalizeFirstLetter.swift
```
## Design Patterns
### 1. **Coordinator Pattern**
- `LunarDatePickerCoordinator` manages the presentation flow and dependencies
- Decouples view controllers from navigation logic
### 2. **Factory Pattern**
- `PickerControllerFactory` creates appropriate picker controllers
- Enables easy testing and configuration
### 3. **Protocol-Oriented Programming**
- `ConfigurationProviding` and `PickerPresenting` protocols
- Enables dependency injection and testability
### 4. **Dependency Injection**
- All major components use constructor injection
- Default implementations provided for convenience
### 5. **Single Responsibility Principle**
- Each class has a single, well-defined responsibility
- Clear separation between UI, business logic, and data
## Key Components
### LunarDatePicker
Main entry point implementing `HybridLunarDatePickerSpec`:
- Validates configuration and presentation parameters
- Delegates to coordinator for actual implementation
- Thread-safe with main thread checking
### LunarDatePickerCoordinator
Manages the overall flow:
- Stores global configuration
- Coordinates between services
- Handles view controller presentation
### ConfigurationBuilder
Builds picker configurations:
- Applies themes, languages, timezone settings
- Validates color formats and data integrity
- Provides type-safe configuration
### PickerPresenter
Handles picker presentation logic:
- Creates appropriate picker controllers
- Configures date ranges and initial values
- Manages completion callbacks
### DateConverter
Utility for date conversions:
- Converts between JavaScript timestamps and Swift Dates
- Handles millisecond precision
- Provides convenience methods for Range creation
## Error Handling
Comprehensive error handling with `LunarDatePickerError`:
- `noRootViewController`: When unable to find root view controller
- `invalidConfiguration`: When configuration validation fails
- `presentationFailed`: When presentation fails
## Thread Safety
- All UI operations ensure execution on main thread
- Automatic dispatch to main thread when needed
- Thread-safe property access
## Testing Considerations
The architecture supports easy unit testing:
- Protocol-based dependencies
- Constructor injection
- Factory pattern for object creation
- Clear separation of concerns
## Usage Example
```swift
// Initialize with default dependencies
let picker = LunarDatePicker()
// Configure global settings
let config = ConfigParams(
themes: ["dark": darkTheme],
languages: ["vi": vietnameseLanguage],
yearRangeOffset: 100,
timeZoneOffset: 7
)
try picker.configure(config: config)
// Present the picker
let params = PresentParams(
theme: "dark",
language: "vi",
title: "Select Date",
textCancel: "Cancel",
mode: .range,
onDone: { range in
print("Selected range: \(range)")
}
)
try picker.present(params: params)
```
## Best Practices
1. **Immutability**: Use `let` for properties where possible
2. **Access Control**: Proper use of `private`, `internal`, and `public`
3. **Documentation**: Comprehensive documentation with Swift DocC format
4. **Error Handling**: Proper error propagation with `throws`
5. **Memory Management**: Weak references in closures to prevent retain cycles
6. **Type Safety**: Leveraging Swift's type system for compile-time safety
## Contributing
When adding new features:
1. Follow the established architecture patterns
2. Add appropriate protocols for new services
3. Use dependency injection for testability
4. Document public APIs with DocC comments
5. Handle errors appropriately
6. Ensure thread safety for UI operations