Skip to content

Commit acab9b5

Browse files
author
coderchan
committed
UIControl Action
1 parent 5d15574 commit acab9b5

10 files changed

+161
-24
lines changed
Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,52 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Gfm-AY-H96">
3+
<device id="retina6_12" orientation="portrait" appearance="light"/>
34
<dependencies>
4-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
5+
<deployment identifier="iOS"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
57
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+
<capability name="System colors in document resources" minToolsVersion="11.0"/>
69
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
710
</dependencies>
811
<scenes>
912
<!--View Controller-->
1013
<scene sceneID="tne-QT-ifu">
1114
<objects>
12-
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
15+
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
1316
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
14-
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
17+
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
1518
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
16-
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
1719
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
20+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
1821
</view>
22+
<navigationItem key="navigationItem" id="3IV-Lv-sFI"/>
1923
</viewController>
2024
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
2125
</objects>
26+
<point key="canvasLocation" x="1057.2519083969464" y="3.5211267605633805"/>
27+
</scene>
28+
<!--Navigation Controller-->
29+
<scene sceneID="BMQ-Nz-lNu">
30+
<objects>
31+
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="Gfm-AY-H96" sceneMemberID="viewController">
32+
<toolbarItems/>
33+
<navigationBar key="navigationBar" contentMode="scaleToFill" id="a2P-AX-nyI">
34+
<rect key="frame" x="0.0" y="118" width="393" height="44"/>
35+
<autoresizingMask key="autoresizingMask"/>
36+
</navigationBar>
37+
<nil name="viewControllers"/>
38+
<connections>
39+
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="C2m-v4-HiZ"/>
40+
</connections>
41+
</navigationController>
42+
<placeholder placeholderIdentifier="IBFirstResponder" id="5qO-uc-KK0" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
43+
</objects>
44+
<point key="canvasLocation" x="130.53435114503816" y="3.5211267605633805"/>
2245
</scene>
2346
</scenes>
47+
<resources>
48+
<systemColor name="systemBackgroundColor">
49+
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
50+
</systemColor>
51+
</resources>
2452
</document>

Example/Example/ViewController.swift

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,53 @@ import SwiftlyUI
1010

1111

1212
class ViewController: UIViewController {
13-
13+
deinit {
14+
print("deinit")
15+
}
16+
/// 返回按钮
17+
lazy var backButton: UIButton = {
18+
let button: UIButton = UIButton.init(type: .custom)
19+
.imageName("navi_back_black", state: .normal)
20+
.frame(width: 44, height: 44)
21+
// .onAction(target: self, action: {$0.onBackButtonAction() })
22+
.onAction(target: self, action: { (vc: ViewController, btn: UIButton) in
23+
vc.onBackButtonAction()
24+
btn.alpha = 0.5
25+
})
26+
.backgroundColor(.orange)
27+
return button
28+
}()
1429
override func viewDidLoad() {
1530
super.viewDidLoad()
31+
view.backgroundColor = .white
1632
print("viewDidLoad")
17-
if #available(iOS 15.0, *) {
18-
createButton3()
19-
} else {
20-
// Fallback on earlier versions
21-
}
2233

34+
35+
36+
createButton4()
37+
}
38+
func onBackButtonAction() {
39+
let vc = ViewController()
40+
vc.view.backgroundColor = .gray
41+
navigationController?.pushViewController(vc, animated: true)
42+
43+
44+
}
45+
func createButton4() {
46+
view.addSubview(backButton)
47+
backButton.centerToSuper()
48+
let image = UIImage.gradient(colors: [.brown, .clear], direction: .leftToRight, size: CGSize(width: 100, height: 40))
49+
let imageView = UIImageView()
50+
.centerX(to: view, offset: 0)
51+
.centerY(to: view, offset: 100)
52+
.frame(width: 100, height: 40)
53+
.cornerRadius(20)
54+
view.addSubview(imageView)
55+
56+
let gra = CAGradientLayer.gradient(colors: [.brown, .clear], direction: .leftToRight)
57+
gra.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
58+
imageView.layer.addSublayer(gra)
2359
}
24-
2560
@available(iOS 15.0, *)
2661
func createButton3() {
2762
let button = UIButton {

Package.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ let package = Package(
1616
// 核心模块(不依赖 SnapKit)
1717
.target(
1818
name: "SwiftlyUI",
19-
path: "SwiftlyUI"
19+
path: "SwiftlyUI",
20+
linkerSettings: [
21+
.linkedFramework("UIKit", .when(platforms: [.iOS]))
22+
]
2023
),
2124
]
2225
)

SwiftlyUI/Source/Core/UIBackgroundConfiguration+SwiftlyUI.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import UIKit
99

10+
#if swift(>=5.5)
1011
@available(iOS 14.0, *)
1112
public extension UIBackgroundConfiguration {
1213

@@ -118,15 +119,15 @@ public extension UIBackgroundConfiguration {
118119
}
119120

120121
// MARK: - 阴影属性 (iOS 18+)
121-
122+
#if compiler(>=6.0)
122123
@available(iOS 18.0, tvOS 18.0, visionOS 2.0, *)
123124
@discardableResult
124125
func shadowProperties(_ properties: UIShadowProperties) -> UIBackgroundConfiguration {
125126
var newConfig = self
126127
newConfig.shadowProperties = properties
127128
return newConfig
128129
}
129-
130+
#endif
130131
// MARK: - 便捷方法
131132

132133
/// 链式更新状态配置
@@ -148,3 +149,4 @@ public extension UIBackgroundConfiguration {
148149
return newConfig
149150
}
150151
}
152+
#endif

SwiftlyUI/Source/Core/UIButton+SwiftlyUI.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public extension UIButton {
162162
return self
163163
}
164164
}
165-
165+
#if swift(>=5.5)
166166
@available(iOS 15.0, *)
167167
public extension UIButton {
168168

@@ -536,7 +536,7 @@ private extension UIButton {
536536
}
537537
}
538538
}
539-
539+
#endif
540540
@MainActor
541541
private struct __UIButtonDisposableClass {
542542
private static var hasExecuted = false

SwiftlyUI/Source/Core/UIColor+SwiftlyUI.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public extension UIColor {
7373

7474

7575
public extension UIColor {
76-
static func convertToCGColors(_ colors: [UIColor]) -> [CGColor] {
76+
static func tosRGBCGColors(_ colors: [UIColor]) -> [CGColor] {
7777
return colors.map { color -> CGColor in
7878
guard let convertedColor = color.cgColor.converted(
7979
to: CGColorSpace(name: CGColorSpace.sRGB)!,

SwiftlyUI/Source/Core/UIControl+SwiftlyUI.swift

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,49 @@ public extension UIControl {
7777

7878
// MARK: - Action
7979
public extension UIControl {
80+
81+
/// .onAction(target: self, action: { $0.doSomething() })
82+
@discardableResult
83+
func onAction<T: AnyObject>(target: T, for event: UIControl.Event = .touchUpInside, action: @escaping (T) -> Void) -> Self {
84+
if let oldWrapper = actionClosures[event.rawValue] {
85+
removeTarget(oldWrapper, action: nil, for: event)
86+
}
87+
88+
if let oldHandler = actionClosures[event.rawValue] as? ActionSingleHandler<T> {
89+
removeTarget(oldHandler, action: nil, for: event)
90+
}
91+
92+
let handler = ActionSingleHandler(target: target, action: action)
93+
addTarget(handler, action: #selector(ActionSingleHandler<T>.invoke), for: event)
94+
actionClosures[event.rawValue] = handler
95+
return self
96+
}
97+
98+
/// .onAction(target: self, action: { (vc: ViewController, btn: UIButton) in vc.doSomething(with: btn) })
99+
@discardableResult
100+
func onAction<T: AnyObject, ControlType: UIControl>(target: T, for event: UIControl.Event = .touchUpInside, action: @escaping (T, ControlType) -> Void) -> Self {
101+
if let oldWrapper = actionClosures[event.rawValue] {
102+
removeTarget(oldWrapper, action: nil, for: event)
103+
}
104+
105+
if let oldHandler = actionClosures[event.rawValue] as? ActionHandler<T, ControlType> {
106+
removeTarget(oldHandler, action: nil, for: event)
107+
}
108+
109+
let handler = ActionHandler(target: target, action: action)
110+
addTarget(handler, action: #selector(ActionHandler<T, ControlType>.invoke(_:)), for: event)
111+
actionClosures[event.rawValue] = handler
112+
return self
113+
}
114+
115+
/// button.onAction { [weak self] in self?.doSomething() }
80116
@discardableResult
81117
func onAction(for event: UIControl.Event = .touchUpInside, action: @escaping () -> Void) -> Self {
82118
return onAction { _ in
83119
action()
84120
}
85121
}
86-
122+
/// button.onAction { [weak self] (btn: UIButton) in self?.doSomething() }
87123
@discardableResult
88124
func onAction<T: UIControl>(for event: UIControl.Event = .touchUpInside, action: @escaping (T) -> Void) -> Self {
89125
if let oldWrapper = actionClosures[event.rawValue] {
@@ -100,12 +136,44 @@ public extension UIControl {
100136
}
101137

102138
@discardableResult
103-
func onAction(_ target: Any?, action:Selector, event: UIControl.Event = .touchUpInside) -> Self {
139+
func onAction(target: Any?, action:Selector, event: UIControl.Event = .touchUpInside) -> Self {
104140
self.addTarget(target, action: action, for: event)
105141
return self
106142
}
107143
}
108144

145+
private class ActionHandler<T: AnyObject, ControlType: UIControl>: NSObject {
146+
private weak var target: T?
147+
private let action: (T, ControlType) -> Void
148+
149+
init(target: T, action: @escaping (T, ControlType) -> Void) {
150+
self.target = target
151+
self.action = action
152+
super.init()
153+
}
154+
155+
@objc func invoke(_ sender: UIControl) {
156+
guard let target = target, let control = sender as? ControlType else { return }
157+
action(target, control)
158+
}
159+
}
160+
161+
private class ActionSingleHandler<T: AnyObject>: NSObject {
162+
private weak var target: T?
163+
private let action: (T) -> Void
164+
165+
init(target: T, action: @escaping (T) -> Void) {
166+
self.target = target
167+
self.action = action
168+
super.init()
169+
}
170+
171+
@objc func invoke() {
172+
guard let target = target else { return }
173+
action(target)
174+
}
175+
}
176+
109177
// MARK: - private
110178
private class ClosureWrapper<T: UIControl>: NSObject {
111179
private weak var button: T?
@@ -142,4 +210,5 @@ private extension UIControl {
142210
)
143211
}
144212
}
213+
145214
}

SwiftlyUI/Source/Core/UIFont+SwiftlyUI.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public extension UIFont {
5959
static var largeTitle: UIFont {
6060
return UIFont.preferredFont(forTextStyle: .largeTitle)
6161
}
62-
62+
#if compiler(>=5.9)
6363
@available(iOS 17.0, *)
6464
static var extraLargeTitle: UIFont {
6565
return UIFont.preferredFont(forTextStyle: .extraLargeTitle)
@@ -69,7 +69,7 @@ public extension UIFont {
6969
static var extraLargeTitle2: UIFont {
7070
return .preferredFont(forTextStyle: .extraLargeTitle2)
7171
}
72-
72+
#endif
7373
static var title: UIFont {
7474
return .preferredFont(forTextStyle: .title1)
7575
}

SwiftlyUI/Source/Extension/CAGradientLayerExtension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import UIKit
1010
public extension CAGradientLayer {
1111
static func gradient(colors: [UIColor], direction: GradientDirection) -> CAGradientLayer {
1212
let gradientLayer = CAGradientLayer()
13-
gradientLayer.colors = UIColor.convertToCGColors(colors)
13+
gradientLayer.colors = colors.map { $0.cgColor }
1414
let (startPoint, endPoint) = direction.gradientPointsForLayer()
1515
gradientLayer.startPoint = startPoint
1616
gradientLayer.endPoint = endPoint

SwiftlyUI/Source/Extension/UIImageExtension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public extension UIImage {
1414
return nil
1515
}
1616

17-
let cgColors = UIColor.convertToCGColors(colors)
17+
let cgColors = UIColor.tosRGBCGColors(colors)
1818
guard let colorSpace = cgColors.first?.colorSpace else {
1919
return nil
2020
}

0 commit comments

Comments
 (0)