# Build ImagePicker from source using SwiftPM FROM swift:5.9 as build WORKDIR /workspace # Copy all project files into the build image COPY . . # Resolve dependencies and build in release mode RUN swift package resolve RUN swift build -c release # Final runtime image (lightweight) FROM debian:bookworm-slim ENV LANG=C.UTF-8 # Install minimal runtime dependencies RUN apt-get update \ && apt-get install -y ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt/ImagePicker # Copy the built artifacts from the build stage COPY --from=build /workspace/.build/release /opt/ImagePicker # Provide a simple entrypoint to verify the library is present CMD ["/bin/bash", "-lc", "ls -la /opt/ImagePicker && echo ImagePicker build artifacts are ready"]
# Ignore VCS directories .git .gitignore # macOS files .DS_Store .AppleDouble .LSOverride # SwiftPM and build artifacts .build .swiftpm .build. # Xcode files *.xcodeproj *.xcworkspace *.xcuserdatad # Dependencies Packages .package.resolved # Logs *.log # Demo projects Demo/ImagePickerDemo
Concerns: Final runtime image does not install bash, yet the CMD uses /bin/bash -lc. Debian slim variants typically do not include bash by default, so the container may fail to start., Swift runtime libraries (e.g., libswift*.so) are not copied or installed in the final image. If the built Swift library depends on the Swift runtime, the resulting image may fail to run those artifacts unless the runtime libs are provided separately., COPY . . in the build stage may unintentionally include large or sensitive files (e.g., tests, CI configs). Consider using .dockerignore to exclude unnecessary files.
# Build ImagePicker from source using SwiftPM FROM swift:5.9 as build WORKDIR /workspace # Copy all project files into the build image COPY . . # Resolve dependencies and build in release mode RUN swift package resolve RUN swift build -c release # Final runtime image (lightweight) FROM swift:5.9-slim ENV LANG=C.UTF-8 # Install minimal runtime dependencies RUN apt-get update \ && apt-get install -y ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt/ImagePicker # Copy the built artifacts from the build stage COPY --from=build /workspace/.build/release /opt/ImagePicker # Provide a simple entrypoint to verify the library is present CMD ["sh", "-lc", "ls -la /opt/ImagePicker && echo ImagePicker build artifacts are ready"]
- Exact error message and exit code
- /workspace/Source/AssetManager.swift:2:8: error: no such module 'UIKit'
- import UIKit
- fatalError
- Exit code: 1
- Full failure snippet:
Building for production...
[1/1] Compiling ImagePicker AssetManager.swift
/workspace/Source/AssetManager.swift:2:8: error: no such module 'UIKit'
import UIKit
^
error: fatalError
...
ERROR: process "/bin/sh -c swift build -c release" did not complete successfully: exit code: 1
- Failing command/step
- [build 5/5] RUN swift build -c release
- Missing packages or files mentioned
- UIKit module missing
- AssetManager.swift imports UIKit (no such module)
- Version mismatch / platform info
- Base image: swift:5.9 (Linux environment)
- UIKit is an Apple platform framework (iOS/macOS) and is not available on Linux. This indicates a platform-targeting mismatch (iOS/UIKit code being built on a Linux Swift image).- Bundle extension
- myResourceBundle() searches all bundles, builds potential paths by appending "ImagePicker.bundle", and returns the first valid Bundle(url:).
- AssetManager.getImage(_ name: String)
- Uses trait collection with displayScale = 3.
- Starts with Bundle.myResourceBundle(); if resourcePath exists and a nested ImagePicker.bundle at resource + "/ImagePicker.bundle" exists, switches to that bundle.
- Loads image with UIImage(named: name, in: bundle, compatibleWith: traitCollection); falls back to an empty UIImage() if not found.
- AssetManager.fetch(withConfiguration configuration, _ completion)
- Requires PHPhotoLibrary authorization status == .authorized; otherwise returns.
- Runs in a background queue.
- Fetches assets:
- If configuration.allowVideoSelection is true: PHAsset.fetchAssets(with: PHFetchOptions()) (all assets).
- Else: PHAsset.fetchAssets(with: .image, options: PHFetchOptions()) (images only).
- If fetchResult.count > 0, builds an assets array by iterating and inserting each object at index 0 (reverses order).
- Calls completion(assets) on the main thread.
- AssetManager.resolveAsset(_ asset, size: CGSize, shouldPreferLowRes: Bool, completion)
- Uses PHImageManager.default() and PHImageRequestOptions.
- deliveryMode: .fastFormat if shouldPreferLowRes is true, otherwise .highQualityFormat.
- isNetworkAccessAllowed = true.
- Requests image for asset with targetSize, .aspectFill.
- If info exists and info["PHImageFileUTIKey"] == nil, calls completion(image) on the main thread.
- AssetManager.resolveAssets(_ assets: [PHAsset], size: CGSize) -> [UIImage]
- Uses synchronous requests (isSynchronous = true).
- For each asset, requests image with targetSize and .aspectFill.
- Appends non-nil images to the result array and returns it.# Multistage Swift build for ImagePicker FROM swift:5.9 as build WORKDIR /workspace # Copy manifest and sources. Copy entire repo to ensure all sources are available to SwiftPM COPY Package.swift ./ COPY . ./ # Resolve dependencies (if any) and build the package from source RUN swift package resolve RUN swift build -c release FROM debian:bookworm-slim as runtime # Install lightweight runtime dependencies RUN apt-get update && apt-get install -y --no-install-recommends bash ca-certificates && rm -rf /var/lib/apt/lists/* WORKDIR /workspace # Bring over the built artifacts and the source code for inspection COPY --from=build /workspace/.build /workspace/.build COPY --from=build /workspace /workspace # Default shell to keep the container interactive for debugging CMD ["/bin/sh", "-lc", "echo ImagePicker Swift package container; exec /bin/sh"]
- Failing command/step: - [build 6/6] RUN swift build -c release - Exact error message and exit code: - /workspace/Source/AssetManager.swift:2:8: error: no such module 'UIKit' - import UIKit - ^ - error: fatalError - exit code: 1 - Missing packages or files mentioned: - no such module 'UIKit' (UIKit is not available on Linux; not provided by Debian bookworm-slim) - Version/platform mismatch info: - Docker image uses Swift 5.9 on Debian bookworm-slim, i.e., a Linux environment. - UIKit is an Apple/iOS framework not available on Linux; code attempts to import UIKit on Linux, causing the build failure. This indicates a target/platform mismatch (iOS-specific code vs. Linux host). - Notes: - There were 2 casing warnings noted earlier in the log, but they are not actionable for this error; the core failure is the missing UIKit module.
- Imports: Foundation, UIKit, Photos.
- Bundle extension
- myResourceBundle() searches all app bundles for a resource at ImagePicker.bundle and returns the first matching Bundle.
- AssetManager
- getImage(name)
- Trait: displayScale = 3.
- Locates resource bundle (checks Bundle.myResourceBundle(); if bundle?.resourcePath exists, uses resourcePath + "/ImagePicker.bundle").
- Loads UIImage(named: name, in: bundle, compatibleWith: traitCollection); returns empty UIImage() if not found.
- fetch(withConfiguration:completion)
- Requires PHPhotoLibrary authorization status == .authorized; otherwise returns.
- Runs in background thread.
- Fetches assets:
- If configuration.allowVideoSelection is true: fetchAssets(with: PHFetchOptions()) (all assets).
- Else: fetchAssets(with: .image, options: PHFetchOptions()) (images only).
- If fetchResult.count > 0, builds an array by inserting each object at index 0 (reverse order).
- Calls completion(assets) on the main thread.
- resolveAsset(_ asset, size: CGSize = 720x1280, shouldPreferLowRes: Bool = false, completion)
- Uses PHImageManager.default() with PHImageRequestOptions.
- deliveryMode: .fastFormat if shouldPreferLowRes, else .highQualityFormat.
- isNetworkAccessAllowed = true.
- Requests image for asset with targetSize, contentMode .aspectFill.
- In completion, if let info, info["PHImageFileUTIKey"] == nil, then calls completion(image) on main thread.
- resolveAssets(_ assets, size: CGSize = 720x1280) -> [UIImage]
- Synchronous image loading via PHImageManager.default().
- For each asset, requests image with isSynchronous = true and contentMode .aspectFill.
- Appends non-nil images to result array; returns [UIImage].
- Default image size (720x1280) used for resolution.
- Key frameworks: Photos for asset handling, Photos fetch/options, and image requests; Bundle for resource loading.No files found matching pattern.
import Foundation
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var latestLocation: CLLocation?
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
}
func startUpdatingLocation() {
locationManager.startUpdatingLocation()
}
func stopUpdatingLocation() {
locationManager.stopUpdatingLocation()
}
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Pick the location with best (= smallest value) horizontal accuracy
latestLocation = locations.sorted { $0.horizontalAccuracy < $1.horizontalAccuracy }.first
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedAlways || status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
} else {
locationManager.stopUpdatingLocation()
}
}
}
- Purpose: ImagePickerConfiguration (NSObject, @objc public) defines UI, behavior, and orientation settings for an image picker. - Imports: AVFoundation, UIKit - Images/UI elements: - indicatorView: UIView with white color at 60% opacity, cornerRadius 4, translatesAutoresizingMaskIntoConstraints = false - Colors (default values): - backgroundColor: (0.15, 0.19, 0.24, 1) - gallerySeparatorColor: black with 0.6 alpha - mainColor: (0.09, 0.11, 0.13, 1) - noImagesColor: (0.86, 0.86, 0.86, 1) - noCameraColor: (0.86, 0.86, 0.86, 1) - settingsColor: white - bottomContainerColor: (0.09, 0.11, 0.13, 1) - Fonts (default values): - numberLabelFont: system 19 bold - doneButton: system 19 medium - flashButton: system 12 medium - noImagesFont: system 18 medium - noCameraFont: system 18 medium - settingsFont: system 16 medium - Titles (default values): - OKButtonTitle: "OK" - cancelButtonTitle: "Cancel" - doneButtonTitle: "Done" - noImagesTitle: "No images available" - noCameraTitle: "Camera is not available" - settingsTitle: "Settings" - requestPermissionTitle: "Permission denied" - requestPermissionMessage: "Please, allow the application to access to your photo library." - Dimensions: - cellSpacing: 2 - indicatorWidth: 41 - indicatorHeight: 8 - Custom behaviours (defaults): - canRotateCamera: true - collapseCollectionViewWhileShot: true - recordLocation: true - allowMultiplePhotoSelection: true - allowVideoSelection: false - showsImageCountLabel: true - flashButtonAlwaysHidden: false - managesAudioSession: true - allowPinchToZoom: true - allowedOrientations: all - allowVolumeButtonsToTakePicture: true - useLowResolutionPreviewImage: false - galleryOnly: false - Orientation logic (extension rotationTransform): - Uses current UIDevice.orientation - If orientation is allowed (portrait, portraitUpsideDown, landscapeLeft, landscapeRight), updates Helper.previousOrientation - If Helper.previousOrientation is unknown, selects a default from allowed orientations in order: portrait, landscapeLeft, landscapeRight, portraitUpsideDown - Returns transform from Helper.getTransform(fromDeviceOrientation: Helper.previousOrientation) - Relies on Helper.previousOrientation and Helper.getTransform - Notes: - Helper type is used for orientation tracking and transform generation; exact implementation not shown.
Summary of actionable items and behavior
- Dependencies: Foundation, UIKit, Photos
- Resource bundle resolution
- Bundle.myResourceBundle(): scans Bundle.allBundles, builds paths by appending "ImagePicker" and "bundle" to each bundle’s resourceURL, returns the first valid Bundle(url: …).
- Image loading
- AssetManager.getImage(_ name: String) -> UIImage
- Creates traitCollection with displayScale = 3.
- Tries to load bundle via Bundle.myResourceBundle(); if resourcePath exists, tries nested bundle at resourcePath + "/ImagePicker.bundle".
- Returns UIImage(named: name, in: bundle, compatibleWith: traitCollection) or an empty UIImage if not found.
- Asset fetching from Photos
- AssetManager.fetch(withConfiguration configuration: ImagePickerConfiguration, _ completion: @escaping (_ assets: [PHAsset]) -> Void)
- Requires PHPhotoLibrary.authorizationStatus() == .authorized; otherwise returns.
- In background, fetches:
- If configuration.allowVideoSelection is true: PHAsset.fetchAssets(with: PHFetchOptions())
- Else: PHAsset.fetchAssets(with: .image, options: PHFetchOptions())
- If fetchResult.count > 0, builds assets array by enumerating and inserting each object at index 0 (reverses order).
- Calls completion(assets) on main thread.
- Single asset resolution
- AssetManager.resolveAsset(_ asset: PHAsset, size: CGSize = 720x1280, shouldPreferLowRes: Bool = false, completion: @escaping (_ image: UIImage?) -> Void)
- Uses PHImageManager.default() with PHImageRequestOptions:
- deliveryMode = shouldPreferLowRes ? .fastFormat : .highQualityFormat
- isNetworkAccessAllowed = true
- Requests image for asset with targetSize = size, contentMode = .aspectFill.
- If info exists and info["PHImageFileUTIKey"] == nil, calls completion(image) on main thread.
- Multiple assets resolution
- AssetManager.resolveAssets(_ assets: [PHAsset], size: CGSize = 720x1280) -> [UIImage]
- Uses PHImageManager.default() with synchronous requests (requestOptions.isSynchronous = true).
- For each asset, requests image with targetSize = size, contentMode = .aspectFill.
- Appends non-nil images to results and returns [UIImage].
Key types/strings to note
- ImagePicker.bundle (resource bundle name)
- ImagePickerConfiguration (configuration parameter used to decide video vs. image fetch)
- PHAsset, PHFetchOptions, PHImageRequestOptions, PHImageManager (Photos framework)
- Target image size defaults: 720x1280
- Display scale default in getImage: 3
Purpose
- Load images from a resource bundle, and fetch/resolve PHAsset images (single or multiple) with options for low-res delivery and network access.No matches found.
# syntax=docker/dockerfile:1
FROM swift:5.9 AS build
WORKDIR /workspace
# Install system dependencies required for SwiftPM on Linux
RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev libsqlite3-dev libicu-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
COPY . .
# Resolve and build the package in release configuration
RUN swift package resolve
RUN swift build -c release
FROM swift:5.9-slim AS runtime
WORKDIR /app
# Copy the built products from the build stage
COPY --from=build /workspace/.build/release /app/.build/release
# Include source and resources for runtime consumers (optional but helpful)
COPY --from=build /workspace/Source /app/Source
COPY --from=build /workspace/Images /app/Images
# Provide an interactive shell to verify the container runs
CMD ["/bin/bash"]
# Ignore VCS and system files .git .gitignore .DS_Store .idea .vscode # SwiftPM build artifacts and intermediate files .build .swiftpm Packages Package.resolved # Xcode and CocoaPods artifacts (not used in this project, but safe to ignore) *.xcodeproj *.xcworkspace ImagePicker.xcodeproj ImagePicker.xcworkspace *.xcarchive Pods Podfile Podfile.lock # Parts of the demo and tests that aren't needed for library build Demo Demo/** # Node or other tooling leftovers node_modules
Summary of Docker build error - Failing command/step: - [build 6/6] RUN swift build -c release - Exact error message and exit code: - /workspace/Source/AssetManager.swift:2:8: error: no such module 'UIKit' - import UIKit - ^ - error: fatalError - Exit code: 1 - Dockerfile: (line showing the failing command) - ERROR: failed to build: failed to solve: process "/bin/sh -c swift build -c release" did not complete successfully: exit code: 1 - Missing packages or files mentioned: - UIKit module not found (no such module 'UIKit') - This indicates UIKit is unavailable in the Linux-based Swift image being used (UIKit is an Apple/iOS framework) - Version mismatch / root cause information: - The build runs in a Linux Swift image (Swift 5.9), attempting to compile code that imports UIKit (an iOS/macOS framework), which is not available on Linux. - This is a platform/framework mismatch: code targets iOS/UIKit but the build environment is Linux-based. Guidance would be to remove or guard UIKit-specific code for non-Apple platforms, or split the build to target macOS/iOS correctly.
- Imports: Foundation, UIKit, Photos
- Bundle extension
- myResourceBundle() -> Bundle?
- Scans Bundle.allBundles, builds paths by appending "ImagePicker" as a non-directory and "bundle" extension to resourceURL
- Returns first Bundle(url:) found from those paths
- AssetManager (open class) with static methods
- getImage(_ name: String) -> UIImage
- traitCollection = UITraitCollection(displayScale: 3)
- var bundle = Bundle.myResourceBundle()
- If bundle?.resourcePath exists and Bundle(path: resource + "/ImagePicker.bundle") exists, set bundle to that resource bundle
- Returns UIImage(named: name, in: bundle, compatibleWith: traitCollection) or a default empty UIImage()
- fetch(withConfiguration configuration: ImagePickerConfiguration, _ completion: @escaping (_ assets: [PHAsset]) -> Void)
- Guards: only proceeds if PHPhotoLibrary.authorizationStatus() == .authorized
- Runs on a global background queue
- fetchResult =
- if configuration.allowVideoSelection is true: PHAsset.fetchAssets(with: PHFetchOptions())
- else: PHAsset.fetchAssets(with: .image, options: PHFetchOptions())
- If fetchResult.count > 0:
- var assets = [PHAsset]()
- enumerateObjects({ object, _, _ in assets.insert(object, at: 0) }) // newest first
- On main queue: completion(assets)
- resolveAsset(_ asset: PHAsset, size: CGSize = CGSize(width: 720, height: 1280), shouldPreferLowRes: Bool = false, completion: @escaping (_ image: UIImage?) -> Void)
- let imageManager = PHImageManager.default()
- let requestOptions = PHImageRequestOptions()
- requestOptions.deliveryMode = shouldPreferLowRes ? .fastFormat : .highQualityFormat
- requestOptions.isNetworkAccessAllowed = true
- imageManager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: requestOptions) { image, info in
- if let info = info, info["PHImageFileUTIKey"] == nil {
- DispatchQueue.main.async { completion(image) }
- }
}
- resolveAssets(_ assets: [PHAsset], size: CGSize = CGSize(width: 720, height: 1280)) -> [UIImage]
- let imageManager = PHImageManager.default()
- let requestOptions = PHImageRequestOptions()
- requestOptions.isSynchronous = true
- var images = [UIImage]()
- For each asset in assets:
- imageManager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: requestOptions) { image, _ in
- if let image = image { images.append(image) }
}
- return images
Key behavioral notes
- getImage uses a 3x display scale trait and attempts to locate ImagePicker.bundle via the resourcePath fallback.
- fetch requires authorization and returns assets in reverse order (newest first) on the main thread.
- resolveAsset supports optional low-res delivery and only calls completion if PHImageFileUTIKey is not present in info.
- resolveAssets uses synchronous image requests and returns an array of UIImages.- Protocol: TopViewDelegate with methods flashButtonDidPress(_ title: String) and rotateDeviceDidPress().
- TopView: UIView subclass with nested Dimensions (leftOffset 11, rightOffset 7, height 34).
- State:
- configuration: ImagePickerConfiguration (default/init may be overridden)
- currentFlashIndex: Int (initial 0)
- flashButtonTitles: ["AUTO", "ON", "OFF"]
- UI elements:
- flashButton (lazy UIButton)
- initial image: AssetManager.getImage("AUTO"), title "AUTO"
- titleEdgeInsets, white title color (normal and highlighted)
- font from configuration.flashButton
- target: flashButtonDidPress
- alignment: left
- accessibilityLabel: "Flash mode is auto"
- accessibilityHint: "Double-tap to change flash mode"
- rotateCamera (lazy UIButton)
- image: AssetManager.getImage("cameraIcon")
- accessibilityHint: "Double-tap to rotate camera"
- target: rotateCameraButtonDidPress
- Delegate: weak var delegate: TopViewDelegate?
- Initializers:
- init(configuration: ImagePickerConfiguration? = nil): uses given configuration if provided, then configure()
- override init(frame: CGRect): calls configure()
- required init?(coder: NSCoder): not implemented
- configure():
- starts with buttons = [flashButton]
- if configuration.canRotateCamera, append rotateCamera
- for each button: apply shadow, disable autoresizing mask, add as subview
- flashButton.isHidden = configuration.flashButtonAlwaysHidden
- calls setupConstraints()
- Actions:
- flashButtonDidPress(_): cycles currentFlashIndex through 0..2
- index 1 (ON): set button title colors to a yellowish tone; highlighted color darker
- other indices: white title color (normal and highlighted)
- update button image to AssetManager.getImage(flashButtonTitles[currentFlashIndex])
- update title to flashButtonTitles[currentFlashIndex]
- accessibilityLabel = "Flash mode is \(newTitle)"
- notify delegate.flashButtonDidPress(newTitle)
- rotateCameraButtonDidPress(_): notify delegate.rotateDeviceDidPress()- Purpose: Swift class ImagePickerConfiguration provides configurable UI and behavior for an image picker.
- Imports: AVFoundation, UIKit
- Class: @objc public class ImagePickerConfiguration: NSObject
- Exposes a large set of @objc public vars for customization
- Colors (default values)
- backgroundColor: RGB (0.15, 0.19, 0.24, alpha 1)
- gallerySeparatorColor: black with 0.6 alpha
- mainColor: RGB (0.09, 0.11, 0.13)
- noImagesColor: RGB (0.86, 0.86, 0.86)
- noCameraColor: RGB (0.86, 0.86, 0.86)
- settingsColor: white
- bottomContainerColor: RGB (0.09, 0.11, 0.13)
- Fonts (default values)
- numberLabelFont: system 19 bold
- doneButton: system 19 medium
- flashButton: system 12 medium
- noImagesFont: system 18 medium
- noCameraFont: system 18 medium
- settingsFont: system 16 medium
- Titles (default values)
- OKButtonTitle: "OK"
- cancelButtonTitle: "Cancel"
- doneButtonTitle: "Done"
- noImagesTitle: "No images available"
- noCameraTitle: "Camera is not available"
- settingsTitle: "Settings"
- requestPermissionTitle: "Permission denied"
- requestPermissionMessage: "Please, allow the application to access to your photo library."
- Dimensions (default values)
- cellSpacing: 2
- indicatorWidth: 41
- indicatorHeight: 8
- Custom behavior flags (defaults)
- canRotateCamera: true
- collapseCollectionViewWhileShot: true
- recordLocation: true
- allowMultiplePhotoSelection: true
- allowVideoSelection: false
- showsImageCountLabel: true
- flashButtonAlwaysHidden: false
- managesAudioSession: true
- allowPinchToZoom: true
- allowedOrientations: all
- allowVolumeButtonsToTakePicture: true
- useLowResolutionPreviewImage: false
- galleryOnly: false
- Images
- indicatorView: a UIView with white 0.6 alpha background, cornerRadius 4, translatesAutoresizingMaskIntoConstraints = false
- Init
- override init() {} (no-op)
- Orientation logic
- Extension: rotationTransform (CGAffineTransform)
- Determines currentOrientation = UIDevice.current.orientation
- If orientation is allowed (portrait, portraitUpsideDown, landscapeLeft, landscapeRight), updates Helper.previousOrientation
- If Helper.previousOrientation is .unknown, selects first available orientation from portrait, landscapeLeft, landscapeRight, portraitUpsideDown
- Returns transform via Helper.getTransform(fromDeviceOrientation: Helper.previousOrientation)
- Dependencies not defined here: Helper (holds previousOrientation and provides getTransform)
- Summary: A comprehensive, @objc-exposed configuration object for customizing colors, fonts, button titles, layout metrics, feature flags, a visual indicator view, and dynamic orientation handling via rotationTransform.Concise summary of actionable items from the tool output (Swift iOS Image Picker)
- Protocol
- ImagePickerDelegate with methods:
- wrapperDidPress(_ imagePicker: ImagePickerController, images: [UIImage])
- doneButtonDidPress(_ imagePicker: ImagePickerController, images: [UIImage])
- cancelButtonDidPress(_ imagePicker: ImagePickerController)
- Core class
- ImagePickerController: manages camera + gallery UI, permissions, volume-triggered capture, and gestures
- Key subviews/assets:
- galleryView: ImageGalleryView
- bottomContainer: BottomContainerView
- topView: TopView
- cameraController: CameraView
- panGestureRecognizer: UIPanGestureRecognizer
- volumeView: MPVolumeView
- Data/state
- delegate: ImagePickerDelegate?
- stack: ImageStack
- imageLimit: Int
- preferredImageSize: CGSize?
- startOnFrontCamera: Bool
- configuration: ImagePickerConfiguration
- doneButtonTitle: String?
- various frame/offset state (initialFrame, initialContentOffset, numberOfCells)
- Lifecycle
- viewDidLoad: builds/subviews and constraints; subscribes to notifications
- viewWillAppear: manages audio session if enabled
- viewDidAppear: configures gallery height, transforms
- deinit: resets audio session if needed; removes observers
- Permissions and assets
- checkStatus(): handles PHPhotoLibrary authorization
- presentAskPermissionAlert(): alerts to request permission; guides to Settings
- permissionGranted(): fetches photos and enables gestures
- resetAssets(), AssetManager.resolveAssets usage
- Notifications (subscription and handlers)
- imageDidPush / imageDidDrop: adjust button title
- stackDidReload: didReloadAssets
- AVSystemController_SystemVolumeDidChangeNotification: volumeChanged
- UIDeviceOrientationDidChangeNotification: handleRotation
- didReloadAssets(notification), volumeChanged(notification), adjustButtonTitle(notification), dismissIfNeeded()
- User actions
- pickerButtonDidPress(): triggers takePicture()
- doneButtonDidPress(): resolves assets (respecting preferredImageSize) and notifies delegate
- cancelButtonDidPress(): notifies delegate
- imageStackViewDidPress(): notifies delegate with current images
- imageToLibrary(): imports asset from library into stack with animation
- cameraNotAvailable(): hides flash/rotate controls; disables picker
- Gestures and gallery behavior
- Pan gestures to collapse/expand gallery
- panGestureDidStart/Change/End
- collapseGalleryView(), showGalleryView(), expandGalleryView()
- updateGalleryViewFrames(_ constant: CGFloat)
- enableGestures(_ enabled: Bool)
- Camera/TopView integration
- setFlashButtonHidden(_ hidden: Bool)
- flashButtonDidPress(_ title: String), rotateDeviceDidPress()
- Orientation and layout
- supportedInterfaceOrientations: portrait
- handleRotation(_ note: Notification?) and applyOrientationTransforms()
- ImageGalleryView.Dimensions.galleryBarHeight referenced for layout
- Helpers and constants
- GestureConstants: maximumHeight, minimumHeight, velocity
- Uses assets from ImageGalleryView, ImageStack, AssetManager
- Configuration-driven texts: requestPermissionTitle, requestPermissionMessage, OKButtonTitle, cancelButtonTitle
- RotationTransform from configuration; canRotateCamera flag
- Dependencies
- UIKit, MediaPlayer, Photos
- AssetManager, ImageStack, ImagePickerConfiguration, ImageGalleryView, CameraView, BottomContainerView, TopView
- Notable behavior
- If imageLimit == 1, automatic dismiss on push (dismissIfNeeded)
- Collapses gallery during shot if configured (collapseCollectionViewWhileShot)
- Volume buttons can trigger takePicture when allowed and volume change reason is explicit
This summarizes the actionable structure, behavior, and integration points of the ImagePickerController tool.// swift-tools-version:5.1
import PackageDescription
let package = Package(
name: "ImagePicker",
platforms: [
.iOS(.v9)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "ImagePicker",
targets: ["ImagePicker"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "ImagePicker",
dependencies: [],
path: "Source")
],
swiftLanguageVersions: [.v5]
)
# A minimal runtime container for an iOS UIKit library # Note: This project cannot be built on Linux/macOS using SwiftPM due to UIKit dependencies. # This image ships the repository contents and a clear message indicating how to build it on macOS. FROM alpine:3.19 # Basic utilities RUN apk add --no-cache bash WORKDIR /app # Copy the repository contents COPY . . # Informational message when the container runs CMD ["bash", "-lc", "echo 'This repository is an iOS library (ImagePicker). It cannot be built inside this Linux container because UIKit is not available on Linux. To build, run on macOS with Xcode or a macOS CI runner. For usage, refer to README.' && exec /bin/bash"]
# A macOS-oriented build container for an iOS ImagePicker library # Building this library with UIKit is not supported on Linux. # This container simply ships the repository and explains how to build it on macOS. FROM debian:bookworm-slim AS base WORKDIR /workspace # Copy repository contents COPY . . # Add a note about build limitations RUN echo "This repository contains an iOS/UIKit ImagePicker library. Building on Linux is not supported." > /workspace/BUILD_NOTE.txt FROM debian:bookworm-slim AS runtime WORKDIR /app COPY --from=base /workspace /app # Show a helpful note when the container starts CMD ["bash", "-lc", "cat BUILD_NOTE.txt; echo; echo 'To build this library, run on macOS with Xcode or a macOS CI agent.'; exec /bin/bash"]
# A macOS-oriented build container for an iOS ImagePicker library
# Building this library with UIKit is not supported on Linux.
# This container simply ships the repository and explains how to build it on macOS.
FROM debian:bookworm-slim AS build
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspace
# Copy repository contents
COPY . .
# Note about build limitations on Linux
RUN echo "This repository is an iOS library (ImagePicker). Building on Linux is not supported." > /BUILD_NOTE.txt
FROM debian:bookworm-slim AS runtime
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy repository contents from build stage
COPY --from=build /workspace /app
# Start with an informative note about build limitations
CMD ["bash", "-lc", "cat /app/BUILD_NOTE.txt; echo; echo 'To build this library, please run on macOS with Xcode or a macOS CI runner.'; exec /bin/bash"]
Concerns: No actual build step: the Dockerfile only copies the repository and writes a note; it does not build the Swift/iOS library (which is Linux-incompatible)., The final CMD references /app/BUILD_NOTE.txt but that file is created in /BUILD_NOTE.txt in the build stage and is not copied into the final image, leading to an error or missing message., No Swift toolchain or macOS build prerequisites are installed; the container cannot build the library on Linux as stated.
# A Linux container that ships the repository with a clear build limitation note # UIKit-based Swift packages cannot be built on Linux. This image is meant for # repository inspection and guidance, not for actual iOS builds. FROM alpine:3.19 AS base RUN apk add --no-cache bash ca-certificates WORKDIR /workspace # Copy repository contents COPY . . # Build note for users RUN echo "This repository is an iOS library (ImagePicker). Building on Linux is not supported because UIKit is unavailable on Linux." > /BUILD_NOTE.txt CMD ["bash", "-lc", "cat /BUILD_NOTE.txt; echo; echo 'To actually build, run on macOS with Xcode or a macOS CI runner.'; ls -la"]
Concerns: No build step present; the image only copies the repository and prints a note, so it does not build from source as required for an approval., The image is described as a placeholder for inspection and guidance, which doesn’t satisfy a build-from-source workflow. Consider adding a minimal build/test step or clarifying its utility.