Skip to content
Merged
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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
runs-on: macOS-latest
strategy:
matrix:
destination: ['platform=iOS Simulator,OS=16.1,name=iPhone 14 Pro Max']
xcode: ['/Applications/Xcode_14.1.app/Contents/Developer']
destination: ['platform=iOS Simulator,OS=18.0,name=iPhone 16 Pro Max']

steps:
- name: Checkout
uses: actions/checkout@v1
- name: Run test
run: xcodebuild test -workspace QRScanner.xcworkspace -scheme UnitTests -destination "${destination}"
uses: actions/checkout@v4
- name: Select latest Xcode
run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
- name: Run unit tests
run: xcodebuild test -workspace QRScanner.xcworkspace -scheme UnitTests -destination "${destination}" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
env:
destination: ${{ matrix.destination }}
DEVELOPER_DIR: ${{ matrix.xcode }}
2 changes: 1 addition & 1 deletion MercariQRScanner.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Pod::Spec.new do |s|
s.license = "MIT"
s.author = { "hitsubunnu" => "idhitsu@gmail.com" }
s.swift_version = "5.0"
s.ios.deployment_target = "10.0"
s.ios.deployment_target = "14.0"
s.source = { :git => "https://github.com/mercari/QRScanner.git", :tag => s.version }
s.source_files = "QRScanner/*.swift", "QRScanner/**/*.swift"
s.resources = "QRScanner/*.xcassets"
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PackageDescription
let package = Package(
name: "QRScanner",
platforms: [
.iOS(.v10),
.iOS(.v14),
],
products: [
.library(
Expand Down
8 changes: 6 additions & 2 deletions QRScanner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
16D0D5EE23570BC800A2EC78 /* QRScanner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16D0D5E423570BC800A2EC78 /* QRScanner.framework */; };
16D0D5F523570BC800A2EC78 /* QRScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 16D0D5E723570BC800A2EC78 /* QRScanner.h */; settings = {ATTRIBUTES = (Public, ); }; };
43820BFF256A29DD0046AC78 /* Bundle+Module.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43820BFE256A29DD0046AC78 /* Bundle+Module.swift */; };
43820C00256A29DD0046AC79 /* QRScannerSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43820BFF256A29DD0046AC79 /* QRScannerSwiftUIView.swift */; };
76124403238BCEA70020466C /* QRScannerViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76124402238BCEA70020466C /* QRScannerViewTests.swift */; };
76E80674238BB26E0000C667 /* QRScannerSpyDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E80673238BB26E0000C667 /* QRScannerSpyDelegate.swift */; };
/* End PBXBuildFile section */
Expand All @@ -37,6 +38,7 @@
16D0D5ED23570BC800A2EC78 /* QRScannerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QRScannerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
16D0D5F423570BC800A2EC78 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
43820BFE256A29DD0046AC78 /* Bundle+Module.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Module.swift"; sourceTree = "<group>"; };
43820BFF256A29DD0046AC79 /* QRScannerSwiftUIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "QRScannerSwiftUIView.swift"; sourceTree = "<group>"; };
76124402238BCEA70020466C /* QRScannerViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScannerViewTests.swift; sourceTree = "<group>"; };
76E80673238BB26E0000C667 /* QRScannerSpyDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerSpyDelegate.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -84,6 +86,7 @@
16D0D5E723570BC800A2EC78 /* QRScanner.h */,
43820BFE256A29DD0046AC78 /* Bundle+Module.swift */,
16A16402235710D80032684C /* QRScannerView.swift */,
43820BFF256A29DD0046AC79 /* QRScannerSwiftUIView.swift */,
16A16404235711240032684C /* QRScannerError.swift */,
16D0D5E823570BC800A2EC78 /* Info.plist */,
16A16406235712360032684C /* Images.xcassets */,
Expand Down Expand Up @@ -231,6 +234,7 @@
16A16405235711240032684C /* QRScannerError.swift in Sources */,
16A16403235710D80032684C /* QRScannerView.swift in Sources */,
43820BFF256A29DD0046AC78 /* Bundle+Module.swift in Sources */,
43820C00256A29DD0046AC79 /* QRScannerSwiftUIView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -306,7 +310,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -364,7 +368,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
Expand Down
3 changes: 3 additions & 0 deletions QRScanner.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 133 additions & 0 deletions QRScanner/QRScannerSwiftUIView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import SwiftUI

// MARK: - QRScannerSwiftUIView
public struct QRScannerSwiftUIView: UIViewRepresentable {

// MARK: - Configuration
public struct Configuration {
public let focusImage: UIImage?
public let focusImagePadding: CGFloat
public let animationDuration: Double
public let isBlurEffectEnabled: Bool

public init(
focusImage: UIImage? = nil,
focusImagePadding: CGFloat = 8.0,
animationDuration: Double = 0.5,
isBlurEffectEnabled: Bool = false
) {
self.focusImage = focusImage
self.focusImagePadding = focusImagePadding
self.animationDuration = animationDuration
self.isBlurEffectEnabled = isBlurEffectEnabled
}
}

// MARK: - Properties
private let configuration: Configuration
private let onSuccess: (String) -> Void
private let onFailure: (QRScannerError) -> Void
private let onTorchActiveChange: ((Bool) -> Void)?
@Binding private var isScanning: Bool
@Binding private var torchActive: Bool

// MARK: - Initializers
public init(
configuration: Configuration = Configuration(),
isScanning: Binding<Bool> = .constant(true),
torchActive: Binding<Bool> = .constant(false),
onSuccess: @escaping (String) -> Void,
onFailure: @escaping (QRScannerError) -> Void,
onTorchActiveChange: ((Bool) -> Void)? = nil
) {
self.configuration = configuration
self._isScanning = isScanning
self._torchActive = torchActive
self.onSuccess = onSuccess
self.onFailure = onFailure
self.onTorchActiveChange = onTorchActiveChange
}

// MARK: - UIViewRepresentable
public func makeUIView(context: Context) -> QRScannerView {
let qrScannerView = QRScannerView()
let input = QRScannerView.Input(
focusImage: configuration.focusImage,
focusImagePadding: configuration.focusImagePadding,
animationDuration: configuration.animationDuration,
isBlurEffectEnabled: configuration.isBlurEffectEnabled
)
qrScannerView.configure(delegate: context.coordinator, input: input)
context.coordinator.qrScannerView = qrScannerView

if isScanning {
qrScannerView.startRunning()
}

return qrScannerView
}

public func updateUIView(_ uiView: QRScannerView, context: Context) {
if isScanning {
uiView.startRunning()
} else {
uiView.stopRunning()
}

uiView.setTorchActive(isOn: torchActive)
}

public func makeCoordinator() -> Coordinator {
Coordinator(
isScanning: $isScanning,
torchActive: $torchActive,
onSuccess: onSuccess,
onFailure: onFailure,
onTorchActiveChange: onTorchActiveChange
)
}

// MARK: - Coordinator
public class Coordinator: NSObject, QRScannerViewDelegate {
@Binding private var isScanning: Bool
@Binding private var torchActive: Bool
private let onSuccess: (String) -> Void
private let onFailure: (QRScannerError) -> Void
private let onTorchActiveChange: ((Bool) -> Void)?

weak var qrScannerView: QRScannerView?

init(
isScanning: Binding<Bool>,
torchActive: Binding<Bool>,
onSuccess: @escaping (String) -> Void,
onFailure: @escaping (QRScannerError) -> Void,
onTorchActiveChange: ((Bool) -> Void)?
) {
self._isScanning = isScanning
self._torchActive = torchActive
self.onSuccess = onSuccess
self.onFailure = onFailure
self.onTorchActiveChange = onTorchActiveChange
}

public func qrScannerView(_ qrScannerView: QRScannerView, didSuccess code: String) {
Task { @MainActor in
self.isScanning = false
}
onSuccess(code)
}

public func qrScannerView(_ qrScannerView: QRScannerView, didFailure error: QRScannerError) {
onFailure(error)
}

public func qrScannerView(_ qrScannerView: QRScannerView, didChangeTorchActive isOn: Bool) {
Task { @MainActor in
self.torchActive = isOn
}
onTorchActiveChange?(isOn)
}
}
}

13 changes: 13 additions & 0 deletions QRScanner/QRScannerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ public class QRScannerView: UIView {
videoDevice.unlockForConfiguration()
}

public override func layoutSubviews() {
super.layoutSubviews()
if previewLayer?.frame != self.bounds {
previewLayer?.frame = self.bounds
blurEffectView.frame = self.bounds

let width = self.bounds.width * 0.618
let x = self.bounds.width * 0.191
let y = self.bounds.height * 0.191
focusImageView.frame = CGRect(x: x, y: y, width: width, height: width)
}
}

deinit {
setTorchActive(isOn: false)
focusImageView.removeFromSuperview()
Expand Down
4 changes: 2 additions & 2 deletions QRScannerSample/QRScannerSample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -292,7 +292,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
Expand Down
Loading