diff --git a/.gitignore b/.gitignore
index a119ed5..c4d34a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.DS_Store
# Xcode
+.swiftpm
build/
*.pbxuser
!default.pbxuser
diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b37768b..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# references:
-# * http://www.objc.io/issue-6/travis-ci.html
-# * https://github.com/supermarin/xcpretty#usage
-
-osx_image: xcode11
-language: swift
-# cache: cocoapods
-# podfile: Example/Podfile
-# before_install:
-# - gem install cocoapods # Since Travis is not always on latest version
-# - pod install --project-directory=Example
-script:
-- pod lib lint
diff --git a/Package.swift b/Package.swift
new file mode 100644
index 0000000..d0356c9
--- /dev/null
+++ b/Package.swift
@@ -0,0 +1,23 @@
+// swift-tools-version:5.1
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "SimpleTwoWayBinding",
+ platforms: [.iOS(.v10)],
+ products: [
+ .library(
+ name: "SimpleTwoWayBinding",
+ targets: ["SimpleTwoWayBinding"]),
+ ],
+ dependencies: [ ],
+ targets: [
+ .target(
+ name: "SimpleTwoWayBinding",
+ dependencies: []),
+ .testTarget(
+ name: "SimpleTwoWayBindingTests",
+ dependencies: ["SimpleTwoWayBinding"]),
+ ]
+)
diff --git a/SimpleTwoWayBinding.podspec b/SimpleTwoWayBinding.podspec
deleted file mode 100644
index 61fdf52..0000000
--- a/SimpleTwoWayBinding.podspec
+++ /dev/null
@@ -1,19 +0,0 @@
-Pod::Spec.new do |s|
- s.name = 'SimpleTwoWayBinding'
- s.version = '0.0.7'
- s.summary = 'Ultra light weight and simple two way binding for iOS UIControls.'
- s.description = <<-DESC
-Ultra light weight and simple two way binding for UIControls.
-Written with love and hope in Swift 5.
- DESC
-
- s.homepage = 'https://github.com/manishkkatoch/SimpleTwoWayBindingIOS'
- s.license = { :type => 'MIT', :file => 'LICENSE' }
- s.author = { 'Manish Katoch' => 'manish.katoch@gmail.com' }
- s.source = { :git => 'https://github.com/manishkkatoch/SimpleTwoWayBindingIOS.git', :tag => s.version.to_s }
- s.ios.deployment_target = '8.0'
-
- s.source_files = 'Sources/**/*'
- s.frameworks = 'UIKit'
- s.swift_version = '5.0'
-end
diff --git a/Sources/BlockBasedSelector/BlockBasedSelector.h b/Sources/BlockBasedSelector/BlockBasedSelector.h
deleted file mode 100644
index 479b313..0000000
--- a/Sources/BlockBasedSelector/BlockBasedSelector.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// BlockBasedSelector.h
-//
-// Created by Charlton Provatas on 11/2/17.
-// Copyright © 2017 CharltonProvatas. All rights reserved.
-//
-
-#import
-
-@interface BlockBasedSelector : NSObject
-
-@end
-
-typedef void (^OBJCBlock)(id foo);
-
-void class_addMethodWithBlock(Class class, SEL newSelector, OBJCBlock block);
-
-
diff --git a/Sources/BlockBasedSelector/BlockBasedSelector.m b/Sources/BlockBasedSelector/BlockBasedSelector.m
deleted file mode 100644
index 24fbf86..0000000
--- a/Sources/BlockBasedSelector/BlockBasedSelector.m
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// BlockBasedSelector.m
-//
-// Created by Charlton Provatas on 11/2/17.
-// Copyright © 2017 CharltonProvatas. All rights reserved.
-//
-
-#import "BlockBasedSelector.h"
-#import
-
-@implementation BlockBasedSelector
-@end
-
-void class_addMethodWithBlock(Class class, SEL newSelector, OBJCBlock block)
-{
- IMP newImplementation = imp_implementationWithBlock(block);
- Method method = class_getInstanceMethod(class, newSelector);
- class_addMethod(class, newSelector, newImplementation, method_getTypeEncoding(method));
-}
diff --git a/Sources/BlockBasedSelector/BlockBasedSelector.swift b/Sources/BlockBasedSelector/BlockBasedSelector.swift
deleted file mode 100644
index 3303eb2..0000000
--- a/Sources/BlockBasedSelector/BlockBasedSelector.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// BlockBasedSelector.swift
-//
-// Created by Charlton Provatas on 11/2/17.
-// Copyright © 2017 CharltonProvatas. All rights reserved.
-
-import Foundation
-import UIKit
-
-func Selector(_ block: @escaping () -> Void) -> Selector {
- let selector = NSSelectorFromString("\(CACurrentMediaTime())")
- class_addMethodWithBlock(_Selector.self, selector) { (_) in block() }
- return selector
-}
-
-let Selector = _Selector.shared
-@objc class _Selector: NSObject {
- static let shared = _Selector()
-}
diff --git a/Sources/Bindable.swift b/Sources/SimpleTwoWayBinding/Bindable.swift
similarity index 69%
rename from Sources/Bindable.swift
rename to Sources/SimpleTwoWayBinding/Bindable.swift
index 91a2ddd..cec1e2e 100644
--- a/Sources/Bindable.swift
+++ b/Sources/SimpleTwoWayBinding/Bindable.swift
@@ -55,15 +55,44 @@ extension Bindable where Self: NSObject {
@discardableResult
public func bind(with observable: Observable) -> BindingReceipt {
- if let _self = self as? UIControl {
- _self.addTarget(Selector, action: Selector{ [weak self] in self?.valueChanged() }, for: [.editingChanged, .valueChanged])
+
+ if let control = self as? UIControl {
+
+ let memoryAddress = String(format: "%p", unsafeBitCast(self, to: UInt.self))
+ let sleeve = ActionClosure { [weak self] in
+ self?.valueChanged()
+ }
+
+ control.addTarget(sleeve,
+ action: #selector(ActionClosure.invoke),
+ for: [.valueChanged, .editingChanged])
+
+ objc_setAssociatedObject(control, memoryAddress, sleeve, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
+
self.binder = observable
if let val = observable.value {
self.updateValue(with: val)
}
+
return self.observe(for: observable) { (value) in
self.updateValue(with: value)
}
- }
+ }
+}
+
+
+private extension NSObject {
+
+ @objc final class ActionClosure: NSObject {
+ private let closure: () -> Void
+
+ init(_ closure: @escaping () -> Void) {
+ self.closure = closure
+ }
+
+ @objc func invoke() {
+ closure()
+ }
+ }
}
diff --git a/Sources/NSObject+Observable.swift b/Sources/SimpleTwoWayBinding/NSObject+Observable.swift
similarity index 89%
rename from Sources/NSObject+Observable.swift
rename to Sources/SimpleTwoWayBinding/NSObject+Observable.swift
index 2410965..2897dcb 100644
--- a/Sources/NSObject+Observable.swift
+++ b/Sources/SimpleTwoWayBinding/NSObject+Observable.swift
@@ -9,7 +9,7 @@ import Foundation
extension NSObject {
@discardableResult
- public func observe(for observable: Observable, with: @escaping (T) -> ()) -> BindingReceipt {
+ public func observe(for observable: Observable, with: @escaping (T) -> Void) -> BindingReceipt {
observable.bind { observable, value in
DispatchQueue.main.async {
with(value)
diff --git a/Sources/Observable+FunctionalConvenience.swift b/Sources/SimpleTwoWayBinding/Observable+FunctionalConvenience.swift
similarity index 100%
rename from Sources/Observable+FunctionalConvenience.swift
rename to Sources/SimpleTwoWayBinding/Observable+FunctionalConvenience.swift
diff --git a/Sources/Observable.swift b/Sources/SimpleTwoWayBinding/Observable.swift
similarity index 97%
rename from Sources/Observable.swift
rename to Sources/SimpleTwoWayBinding/Observable.swift
index c74f378..b3f9b9f 100644
--- a/Sources/Observable.swift
+++ b/Sources/SimpleTwoWayBinding/Observable.swift
@@ -16,40 +16,40 @@ public struct BindingReceipt: Hashable, Identifiable {
public class Observable {
public typealias Observer = (_ observable: Observable, ObservedType) -> Void
-
+
/// Map of receipt objects to the binding blocks those objects represent; see bind(observer:) and unbind(:)
private var observers: [BindingReceipt: Observer] = [:]
/// Map of other observers we've been bound to; see map(:) & other functional conveniences. This allows us to hold strong references to the anonymous observables generated in a chained series of calls, and break them when needed.
private var bindings: [BindingReceipt: () -> Void] = [:]
-
+
internal var paused: Bool = false
-
+
public var value: ObservedType? {
didSet { fire() }
}
-
+
/// Notify all observers with the current value if non-nil.
public func fire() {
if let value = value {
notifyObservers(value)
}
}
-
+
public init(_ value: ObservedType? = nil) {
self.value = value
}
-
+
@discardableResult
public func bind(observer: @escaping Observer) -> BindingReceipt {
let r = BindingReceipt()
observers[r] = observer
return r
}
-
+
public func setObserving(_ referenceHolder: @escaping () -> Void, receipt: BindingReceipt) {
bindings[receipt] = referenceHolder
}
-
+
public func unbind(_ r: BindingReceipt) {
guard observers[r] != nil else {
print("Warning: attempted to unbind with an invalid receipt")
@@ -58,15 +58,14 @@ public class Observable {
observers[r] = nil
bindings[r] = nil
}
-
+
internal func notifyObservers(_ value: ObservedType) {
observers.values.forEach { [unowned self] observer in
guard paused == false else { return }
observer(self, value)
}
}
-
-
-
-}
+
+
+}
diff --git a/Sources/PausableObservable.swift b/Sources/SimpleTwoWayBinding/PausableObservable.swift
similarity index 99%
rename from Sources/PausableObservable.swift
rename to Sources/SimpleTwoWayBinding/PausableObservable.swift
index 2bdf9b8..5ad4570 100644
--- a/Sources/PausableObservable.swift
+++ b/Sources/SimpleTwoWayBinding/PausableObservable.swift
@@ -5,7 +5,7 @@
// Created by Ryan Forsythe on 6/15/20.
//
-import Foundation
+import UIKit
/// A helper class to manage pausable receipts
public class ReceiptBag {
diff --git a/Sources/UIControls+Bindable.swift b/Sources/SimpleTwoWayBinding/UIControls+Bindable.swift
similarity index 92%
rename from Sources/UIControls+Bindable.swift
rename to Sources/SimpleTwoWayBinding/UIControls+Bindable.swift
index 133578c..105cef7 100644
--- a/Sources/UIControls+Bindable.swift
+++ b/Sources/SimpleTwoWayBinding/UIControls+Bindable.swift
@@ -5,9 +5,9 @@
// Created by Manish Katoch on 11/26/17.
//
-import Foundation
+import UIKit
-extension UITextField : Bindable {
+extension UITextField: Bindable {
public typealias BindingType = String
public func observingValue() -> String? {
@@ -21,7 +21,7 @@ extension UITextField : Bindable {
}
}
-extension UISwitch : Bindable {
+extension UISwitch: Bindable {
public typealias BindingType = Bool
public func observingValue() -> Bool? {
@@ -33,7 +33,7 @@ extension UISwitch : Bindable {
}
}
-extension UISlider : Bindable {
+extension UISlider: Bindable {
public typealias BindingType = Float
public func observingValue() -> Float? {
@@ -45,7 +45,7 @@ extension UISlider : Bindable {
}
}
-extension UIStepper : Bindable {
+extension UIStepper: Bindable {
public typealias BindingType = Double
public func observingValue() -> Double? {
@@ -57,7 +57,7 @@ extension UIStepper : Bindable {
}
}
-extension UISegmentedControl : Bindable {
+extension UISegmentedControl: Bindable {
public typealias BindingType = Int
public func observingValue() -> Int? {
diff --git a/Sources/SimpleTwoWayBindings-Bridging-Header.h b/Sources/SimpleTwoWayBindings-Bridging-Header.h
deleted file mode 100644
index 10c68b0..0000000
--- a/Sources/SimpleTwoWayBindings-Bridging-Header.h
+++ /dev/null
@@ -1,8 +0,0 @@
-//
-// SimpleTwoWayBindings-Bridging-Header.h
-// Pods
-//
-// Created by Manich Katoch on 11/26/17.
-//
-
-#import "BlockBasedSelector.h"
diff --git a/Tests/SimpleTwoWayBindingTests.swift b/Tests/SimpleTwoWayBindingTests/SimpleTwoWayBindingTests.swift
similarity index 100%
rename from Tests/SimpleTwoWayBindingTests.swift
rename to Tests/SimpleTwoWayBindingTests/SimpleTwoWayBindingTests.swift