├── .gitignore
├── README.md
├── Tests
├── LinuxMain.swift
└── BxRefreshableScrollViewTests
│ ├── XCTestManifests.swift
│ └── BxRefreshableScrollViewTests.swift
├── BxRefreshableScrollView.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── Sources
└── BxRefreshableScrollView
│ ├── ActivityIndicator.swift
│ ├── BxRefreshableScrollView.h
│ ├── RefreshableKey.swift
│ └── BxRefreshableScrollView.swift
└── Package.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BxRefreshableScrollView
2 |
3 | A description of this package.
4 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import BxRefreshableScrollViewTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += BxRefreshableScrollViewTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/BxRefreshableScrollView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/Tests/BxRefreshableScrollViewTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(BxRefreshableScrollViewTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Tests/BxRefreshableScrollViewTests/BxRefreshableScrollViewTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import BxRefreshableScrollView
3 |
4 | final class BxRefreshableScrollViewTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertEqual(BxRefreshableScrollView().text, "Hello, World!")
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/BxRefreshableScrollView/ActivityIndicator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActivityIndicator.swift
3 | // BxRefreshableScrollView
4 | //
5 | // Created by Mars on 2020/1/17.
6 | // Copyright © 2020 Mars. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftUI
11 |
12 | struct ActivityIndicator: UIViewRepresentable {
13 | func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView {
14 | return UIActivityIndicatorView()
15 | }
16 |
17 | func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) {
18 | uiView.startAnimating()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/BxRefreshableScrollView/BxRefreshableScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // BxRefreshableScrollView.h
3 | // BxRefreshableScrollView
4 | //
5 | // Created by Mars on 2020/1/17.
6 | // Copyright © 2020 Mars. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for BxRefreshableScrollView.
12 | FOUNDATION_EXPORT double BxRefreshableScrollViewVersionNumber;
13 |
14 | //! Project version string for BxRefreshableScrollView.
15 | FOUNDATION_EXPORT const unsigned char BxRefreshableScrollViewVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "BxRefreshableScrollView",
8 | platforms: [
9 | .iOS(.v13)
10 | ],
11 | products: [
12 | // Products define the executables and libraries a package produces, and make them visible to other packages.
13 | .library(
14 | name: "BxRefreshableScrollView",
15 | targets: ["BxRefreshableScrollView"]),
16 | ],
17 | dependencies: [
18 | // Dependencies declare other packages that this package depends on.
19 | // .package(url: /* package url */, from: "1.0.0"),
20 | ],
21 | targets: [
22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
23 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
24 | .target(
25 | name: "BxRefreshableScrollView",
26 | dependencies: []),
27 | .testTarget(
28 | name: "BxRefreshableScrollViewTests",
29 | dependencies: ["BxRefreshableScrollView"]),
30 | ]
31 | )
32 |
--------------------------------------------------------------------------------
/Sources/BxRefreshableScrollView/RefreshableKey.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RefreshableKey.swift
3 | // BxRefreshableScrollView
4 | //
5 | // Created by Mars on 2020/1/17.
6 | // Copyright © 2020 Mars. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import Foundation
11 |
12 | struct RefreshableKey {
13 | enum ViewType: Int {
14 | case movingView
15 | case fixedView
16 | case contentView
17 | }
18 |
19 | struct PrefData: Equatable {
20 | let vType: ViewType
21 | var bounds: CGRect
22 | }
23 |
24 | struct PrefKey: PreferenceKey {
25 | typealias Value = [PrefData]
26 | static var defaultValue: [PrefData] = []
27 |
28 | static func reduce(
29 | value: inout [RefreshableKey.PrefData],
30 | nextValue: () -> [RefreshableKey.PrefData]) {
31 | value.append(contentsOf: nextValue())
32 | }
33 | }
34 |
35 | struct ContentPrefData {
36 | let vType: ViewType
37 | let bounds: Anchor
38 | }
39 |
40 | struct ContentPrefKey: PreferenceKey {
41 | typealias Value = [ContentPrefData]
42 | static var defaultValue: [ContentPrefData] = []
43 |
44 | static func reduce(
45 | value: inout [RefreshableKey.ContentPrefData],
46 | nextValue: () -> [RefreshableKey.ContentPrefData]) {
47 | value.append(contentsOf: nextValue())
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Sources/BxRefreshableScrollView/BxRefreshableScrollView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BxRefreshableScrollView.swift
3 | // BxRefreshableScrollView
4 | //
5 | // Created by Mars on 2020/1/17.
6 | // Copyright © 2020 Mars. All rights reserved.
7 | //
8 | import Combine
9 | import SwiftUI
10 |
11 | //private var contentBounds: CGRect = .zero
12 |
13 | public struct RefreshableScrollView: View {
14 | @State private var previousScrollOffset: CGFloat = 0
15 | @State private var scrollOffset: CGFloat = 0
16 |
17 | // Keep the loading indication area above the scroll view.
18 | @State private var frozen: Bool = false
19 | @State private var rotation: Angle = .degrees(0)
20 |
21 | // Trigger the action after scrolling over the threshold.
22 | var threshold: CGFloat = 80
23 |
24 | // Pull down to refresh
25 | @Binding var refreshing: Bool
26 |
27 | // Pull up to refresh
28 | private let bottomRefreshable: Bool
29 | @Binding var showNoMoreData: Bool
30 | @Binding var showBottomLoading: Bool
31 | var noDataPrompt: String
32 |
33 | @State var contentBounds: CGRect = .zero
34 |
35 | let content: Content
36 |
37 | public init(height: CGFloat = 80,
38 | refreshing: Binding,
39 | bottomRefreshable: Bool = false,
40 | showNoMoreData: Binding = .constant(false),
41 | showBottomLoading: Binding = .constant(false),
42 | noDataPrompt: String = "",
43 | @ViewBuilder content: () -> Content) {
44 | self.threshold = height
45 | self._refreshing = refreshing
46 | self.bottomRefreshable = bottomRefreshable
47 | self._showNoMoreData = showNoMoreData
48 | self._showBottomLoading = showBottomLoading
49 | self.noDataPrompt = noDataPrompt
50 | self.content = content()
51 | }
52 |
53 | public var body: some View {
54 | ScrollView {
55 | ZStack(alignment: .top) {
56 | MovingView()
57 | VStack {
58 | /// GeometryReader {
59 | /// self.content.preference(
60 | /// key: RefreshableKey.PrefKey.self,
61 | /// value: [
62 | /// RefreshableKey.PrefData(vType: .contentView,
63 | /// bounds: $0.frame(in: CoordinateSpace.local))
64 | /// ]) }
65 | self.content
66 | .anchorPreference(
67 | key: RefreshableKey.ContentPrefKey.self,
68 | value: .bounds,
69 | transform: { [RefreshableKey.ContentPrefData(vType: .contentView, bounds: $0)] })
70 |
71 | if bottomRefreshable {
72 | ZStack {
73 | ActivityIndicator().opacity(showBottomLoading ? 1 : 0)
74 | Text(noDataPrompt).opacity(showNoMoreData ? 1 : 0)
75 | }
76 | .foregroundColor(Color.secondary)
77 | .padding([.top, .bottom], 5)
78 | }
79 | }
80 | .alignmentGuide(.top, computeValue: { d in (self.refreshing && self.frozen ? -self.threshold : 0.0) })
81 | SymbolView(height: self.threshold, loading: self.refreshing, frozen: self.frozen, rotation: self.rotation)
82 | }
83 | }
84 | // .backgroundPreferenceValue(RefreshableKey.PrefKey.self) {
85 | // (preferences: [RefreshableKey.PrefData]) in
86 | // return GeometryReader { (proxy: GeometryProxy) -> FixedView in
87 | // let p = preferences.first(where: { $0.vType == .contentView })!
88 | // self.contentBounds = p.bounds
89 | //
90 | // return FixedView()
91 | // }
92 | // }
93 | .backgroundPreferenceValue(RefreshableKey.ContentPrefKey.self) {
94 | (preferences: [RefreshableKey.ContentPrefData]) in
95 | return GeometryReader { (proxy: GeometryProxy) -> FixedView in
96 | if self.bottomRefreshable {
97 | let p = preferences.first(where: { $0.vType == .contentView })
98 |
99 | DispatchQueue.main.async {
100 | if let pref = p {
101 | self.contentBounds = proxy[pref.bounds]
102 | }
103 | }
104 | }
105 |
106 | return FixedView()
107 | }
108 | }
109 | .onPreferenceChange(RefreshableKey.PrefKey.self ) { preferences in
110 | self.refreshLogic(values: preferences)
111 | }
112 | }
113 |
114 | func refreshLogic(values: [RefreshableKey.PrefData]) {
115 | let movingBounds = values.first { $0.vType == .movingView }?.bounds ?? .zero
116 | let fixedBounds = values.first { $0.vType == .fixedView }?.bounds ?? .zero
117 |
118 | scrollOffset = movingBounds.minY - fixedBounds.minY
119 | rotation = symbolRotation(scrollOffset)
120 |
121 | // Crossing the threshold on the way down, we start the refreshing process
122 | if !refreshing && (scrollOffset > threshold && previousScrollOffset <= threshold) {
123 | refreshing = true
124 | }
125 |
126 | if refreshing {
127 | /// Keep the symbol view above the scrollview during updating process.
128 | /// `self.scrollOffset <= self.threshold` prevents the UI from scrolling back
129 | /// to the top of screen.
130 | if previousScrollOffset > threshold && scrollOffset <= threshold {
131 | frozen = true
132 | }
133 | }
134 | else {
135 | frozen = false
136 | }
137 |
138 | #if DEBUG
139 | print("Scroll offset: \(scrollOffset)")
140 | print("Fix height: \(fixedBounds.size.height)")
141 | print("Content bounds: \(contentBounds)")
142 | print("-------------------------")
143 | #endif
144 | if bottomRefreshable,
145 | contentBounds.height > 0 &&
146 | scrollOffset < -(contentBounds.height - fixedBounds.size.height) &&
147 | showBottomLoading == false &&
148 | showNoMoreData == false {
149 | print("display bottom indicator")
150 | showBottomLoading = true
151 | }
152 |
153 | previousScrollOffset = scrollOffset
154 | }
155 |
156 | func symbolRotation(_ scrollOffset: CGFloat) -> Angle {
157 | if scrollOffset < threshold * 0.6 {
158 | return .degrees(0)
159 | }
160 | else {
161 | let h = Double(threshold)
162 | let d = Double(scrollOffset)
163 | let v = max(min(d - (h * 0.6), h * 0.4), 0)
164 |
165 | return .degrees(180 * v / (h * 0.4))
166 | }
167 | }
168 |
169 | struct SymbolView: View {
170 | var height: CGFloat
171 | var loading: Bool
172 | var frozen: Bool
173 | var rotation: Angle
174 |
175 | var body: some View {
176 | Group {
177 | if loading {
178 | VStack {
179 | Spacer()
180 | ActivityIndicator()
181 | Spacer()
182 | }
183 | .frame(height: height).fixedSize()
184 | .offset(y: -height + (loading && frozen ? height : 0))
185 | }
186 | else {
187 | Image(systemName: "arrow.down")
188 | .resizable()
189 | .aspectRatio(contentMode: .fit)
190 | .frame(width: height * 0.25, height: height*0.25).fixedSize()
191 | .padding(height * 0.375)
192 | .rotationEffect(rotation)
193 | .offset(y: -height + (loading && frozen ? height : 0))
194 | }
195 | }
196 | }
197 | }
198 |
199 | struct MovingView: View {
200 | var body: some View {
201 | GeometryReader {
202 | Color.clear
203 | /// Compare to:
204 | /// ```
205 | /// .anchorPreference(key: TagPreferenceKey.self,
206 | /// value: .bounds,
207 | /// transform: { [TagPreferenceData(bounds: $0)] })
208 | /// ```
209 | .preference(key: RefreshableKey.PrefKey.self,
210 | value: [RefreshableKey.PrefData(vType: .movingView, bounds: $0.frame(in: .global))])
211 | }
212 | .frame(height: 0)
213 | }
214 | }
215 |
216 | struct FixedView: View {
217 | var body: some View {
218 | GeometryReader {
219 | Color.clear
220 | .preference(key: RefreshableKey.PrefKey.self,
221 | value: [RefreshableKey.PrefData(vType: .fixedView, bounds: $0.frame(in: .global))])
222 | }
223 | }
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/BxRefreshableScrollView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = "1";
4 | objectVersion = "46";
5 | objects = {
6 | "BxRefreshableScrollView::BxRefreshableScrollView" = {
7 | isa = "PBXNativeTarget";
8 | buildConfigurationList = "OBJ_23";
9 | buildPhases = (
10 | "OBJ_26",
11 | "OBJ_30"
12 | );
13 | dependencies = (
14 | );
15 | name = "BxRefreshableScrollView";
16 | productName = "BxRefreshableScrollView";
17 | productReference = "BxRefreshableScrollView::BxRefreshableScrollView::Product";
18 | productType = "com.apple.product-type.framework";
19 | };
20 | "BxRefreshableScrollView::BxRefreshableScrollView::Product" = {
21 | isa = "PBXFileReference";
22 | path = "BxRefreshableScrollView.framework";
23 | sourceTree = "BUILT_PRODUCTS_DIR";
24 | };
25 | "BxRefreshableScrollView::BxRefreshableScrollViewPackageTests::ProductTarget" = {
26 | isa = "PBXAggregateTarget";
27 | buildConfigurationList = "OBJ_38";
28 | buildPhases = (
29 | );
30 | dependencies = (
31 | "OBJ_41"
32 | );
33 | name = "BxRefreshableScrollViewPackageTests";
34 | productName = "BxRefreshableScrollViewPackageTests";
35 | };
36 | "BxRefreshableScrollView::BxRefreshableScrollViewTests" = {
37 | isa = "PBXNativeTarget";
38 | buildConfigurationList = "OBJ_43";
39 | buildPhases = (
40 | "OBJ_46",
41 | "OBJ_49"
42 | );
43 | dependencies = (
44 | "OBJ_51"
45 | );
46 | name = "BxRefreshableScrollViewTests";
47 | productName = "BxRefreshableScrollViewTests";
48 | productReference = "BxRefreshableScrollView::BxRefreshableScrollViewTests::Product";
49 | productType = "com.apple.product-type.bundle.unit-test";
50 | };
51 | "BxRefreshableScrollView::BxRefreshableScrollViewTests::Product" = {
52 | isa = "PBXFileReference";
53 | path = "BxRefreshableScrollViewTests.xctest";
54 | sourceTree = "BUILT_PRODUCTS_DIR";
55 | };
56 | "BxRefreshableScrollView::SwiftPMPackageDescription" = {
57 | isa = "PBXNativeTarget";
58 | buildConfigurationList = "OBJ_32";
59 | buildPhases = (
60 | "OBJ_35"
61 | );
62 | dependencies = (
63 | );
64 | name = "BxRefreshableScrollViewPackageDescription";
65 | productName = "BxRefreshableScrollViewPackageDescription";
66 | productType = "com.apple.product-type.framework";
67 | };
68 | "OBJ_1" = {
69 | isa = "PBXProject";
70 | attributes = {
71 | LastSwiftMigration = "9999";
72 | LastUpgradeCheck = "9999";
73 | };
74 | buildConfigurationList = "OBJ_2";
75 | compatibilityVersion = "Xcode 3.2";
76 | developmentRegion = "en";
77 | hasScannedForEncodings = "0";
78 | knownRegions = (
79 | "en"
80 | );
81 | mainGroup = "OBJ_5";
82 | productRefGroup = "OBJ_18";
83 | projectDirPath = ".";
84 | targets = (
85 | "BxRefreshableScrollView::BxRefreshableScrollView",
86 | "BxRefreshableScrollView::SwiftPMPackageDescription",
87 | "BxRefreshableScrollView::BxRefreshableScrollViewPackageTests::ProductTarget",
88 | "BxRefreshableScrollView::BxRefreshableScrollViewTests"
89 | );
90 | };
91 | "OBJ_10" = {
92 | isa = "PBXFileReference";
93 | path = "Info.plist";
94 | sourceTree = "";
95 | };
96 | "OBJ_11" = {
97 | isa = "PBXFileReference";
98 | path = "ActivityIndicator.swift";
99 | sourceTree = "";
100 | };
101 | "OBJ_12" = {
102 | isa = "PBXFileReference";
103 | path = "BxRefreshableScrollView.swift";
104 | sourceTree = "";
105 | };
106 | "OBJ_13" = {
107 | isa = "PBXFileReference";
108 | path = "RefreshableKey.swift";
109 | sourceTree = "";
110 | };
111 | "OBJ_14" = {
112 | isa = "PBXGroup";
113 | children = (
114 | "OBJ_15"
115 | );
116 | name = "Tests";
117 | path = "";
118 | sourceTree = "SOURCE_ROOT";
119 | };
120 | "OBJ_15" = {
121 | isa = "PBXGroup";
122 | children = (
123 | "OBJ_16",
124 | "OBJ_17"
125 | );
126 | name = "BxRefreshableScrollViewTests";
127 | path = "Tests/BxRefreshableScrollViewTests";
128 | sourceTree = "SOURCE_ROOT";
129 | };
130 | "OBJ_16" = {
131 | isa = "PBXFileReference";
132 | path = "BxRefreshableScrollViewTests.swift";
133 | sourceTree = "";
134 | };
135 | "OBJ_17" = {
136 | isa = "PBXFileReference";
137 | path = "XCTestManifests.swift";
138 | sourceTree = "";
139 | };
140 | "OBJ_18" = {
141 | isa = "PBXGroup";
142 | children = (
143 | "BxRefreshableScrollView::BxRefreshableScrollViewTests::Product",
144 | "BxRefreshableScrollView::BxRefreshableScrollView::Product"
145 | );
146 | name = "Products";
147 | path = "";
148 | sourceTree = "BUILT_PRODUCTS_DIR";
149 | };
150 | "OBJ_2" = {
151 | isa = "XCConfigurationList";
152 | buildConfigurations = (
153 | "OBJ_3",
154 | "OBJ_4"
155 | );
156 | defaultConfigurationIsVisible = "0";
157 | defaultConfigurationName = "Release";
158 | };
159 | "OBJ_21" = {
160 | isa = "PBXFileReference";
161 | path = "README.md";
162 | sourceTree = "";
163 | };
164 | "OBJ_23" = {
165 | isa = "XCConfigurationList";
166 | buildConfigurations = (
167 | "OBJ_24",
168 | "OBJ_25"
169 | );
170 | defaultConfigurationIsVisible = "0";
171 | defaultConfigurationName = "Release";
172 | };
173 | "OBJ_24" = {
174 | isa = "XCBuildConfiguration";
175 | buildSettings = {
176 | ENABLE_TESTABILITY = "YES";
177 | FRAMEWORK_SEARCH_PATHS = (
178 | "$(inherited)",
179 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
180 | );
181 | HEADER_SEARCH_PATHS = (
182 | "$(inherited)"
183 | );
184 | INFOPLIST_FILE = "BxRefreshableScrollView.xcodeproj/BxRefreshableScrollView_Info.plist";
185 | IPHONEOS_DEPLOYMENT_TARGET = "9.0";
186 | LD_RUNPATH_SEARCH_PATHS = (
187 | "$(inherited)",
188 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"
189 | );
190 | MACOSX_DEPLOYMENT_TARGET = "10.10";
191 | OTHER_CFLAGS = (
192 | "$(inherited)"
193 | );
194 | OTHER_LDFLAGS = (
195 | "$(inherited)"
196 | );
197 | OTHER_SWIFT_FLAGS = (
198 | "$(inherited)"
199 | );
200 | PRODUCT_BUNDLE_IDENTIFIER = "BxRefreshableScrollView";
201 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
202 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
203 | SKIP_INSTALL = "YES";
204 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
205 | "$(inherited)"
206 | );
207 | SWIFT_VERSION = "5.0";
208 | TARGET_NAME = "BxRefreshableScrollView";
209 | TVOS_DEPLOYMENT_TARGET = "9.0";
210 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
211 | };
212 | name = "Debug";
213 | };
214 | "OBJ_25" = {
215 | isa = "XCBuildConfiguration";
216 | buildSettings = {
217 | ENABLE_TESTABILITY = "YES";
218 | FRAMEWORK_SEARCH_PATHS = (
219 | "$(inherited)",
220 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
221 | );
222 | HEADER_SEARCH_PATHS = (
223 | "$(inherited)"
224 | );
225 | INFOPLIST_FILE = "BxRefreshableScrollView.xcodeproj/BxRefreshableScrollView_Info.plist";
226 | IPHONEOS_DEPLOYMENT_TARGET = "9.0";
227 | LD_RUNPATH_SEARCH_PATHS = (
228 | "$(inherited)",
229 | "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"
230 | );
231 | MACOSX_DEPLOYMENT_TARGET = "10.10";
232 | OTHER_CFLAGS = (
233 | "$(inherited)"
234 | );
235 | OTHER_LDFLAGS = (
236 | "$(inherited)"
237 | );
238 | OTHER_SWIFT_FLAGS = (
239 | "$(inherited)"
240 | );
241 | PRODUCT_BUNDLE_IDENTIFIER = "BxRefreshableScrollView";
242 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
243 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
244 | SKIP_INSTALL = "YES";
245 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
246 | "$(inherited)"
247 | );
248 | SWIFT_VERSION = "5.0";
249 | TARGET_NAME = "BxRefreshableScrollView";
250 | TVOS_DEPLOYMENT_TARGET = "9.0";
251 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
252 | };
253 | name = "Release";
254 | };
255 | "OBJ_26" = {
256 | isa = "PBXSourcesBuildPhase";
257 | files = (
258 | "OBJ_27",
259 | "OBJ_28",
260 | "OBJ_29"
261 | );
262 | };
263 | "OBJ_27" = {
264 | isa = "PBXBuildFile";
265 | fileRef = "OBJ_11";
266 | };
267 | "OBJ_28" = {
268 | isa = "PBXBuildFile";
269 | fileRef = "OBJ_12";
270 | };
271 | "OBJ_29" = {
272 | isa = "PBXBuildFile";
273 | fileRef = "OBJ_13";
274 | };
275 | "OBJ_3" = {
276 | isa = "XCBuildConfiguration";
277 | buildSettings = {
278 | CLANG_ENABLE_OBJC_ARC = "YES";
279 | COMBINE_HIDPI_IMAGES = "YES";
280 | COPY_PHASE_STRIP = "NO";
281 | DEBUG_INFORMATION_FORMAT = "dwarf";
282 | DYLIB_INSTALL_NAME_BASE = "@rpath";
283 | ENABLE_NS_ASSERTIONS = "YES";
284 | GCC_OPTIMIZATION_LEVEL = "0";
285 | GCC_PREPROCESSOR_DEFINITIONS = (
286 | "$(inherited)",
287 | "SWIFT_PACKAGE=1",
288 | "DEBUG=1"
289 | );
290 | MACOSX_DEPLOYMENT_TARGET = "10.10";
291 | ONLY_ACTIVE_ARCH = "YES";
292 | OTHER_SWIFT_FLAGS = (
293 | "$(inherited)",
294 | "-DXcode"
295 | );
296 | PRODUCT_NAME = "$(TARGET_NAME)";
297 | SDKROOT = "macosx";
298 | SUPPORTED_PLATFORMS = (
299 | "macosx",
300 | "iphoneos",
301 | "iphonesimulator",
302 | "appletvos",
303 | "appletvsimulator",
304 | "watchos",
305 | "watchsimulator"
306 | );
307 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
308 | "$(inherited)",
309 | "SWIFT_PACKAGE",
310 | "DEBUG"
311 | );
312 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
313 | USE_HEADERMAP = "NO";
314 | };
315 | name = "Debug";
316 | };
317 | "OBJ_30" = {
318 | isa = "PBXFrameworksBuildPhase";
319 | files = (
320 | );
321 | };
322 | "OBJ_32" = {
323 | isa = "XCConfigurationList";
324 | buildConfigurations = (
325 | "OBJ_33",
326 | "OBJ_34"
327 | );
328 | defaultConfigurationIsVisible = "0";
329 | defaultConfigurationName = "Release";
330 | };
331 | "OBJ_33" = {
332 | isa = "XCBuildConfiguration";
333 | buildSettings = {
334 | LD = "/usr/bin/true";
335 | OTHER_SWIFT_FLAGS = (
336 | "-swift-version",
337 | "5",
338 | "-I",
339 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2",
340 | "-sdk",
341 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk",
342 | "-package-description-version",
343 | "5.3.0"
344 | );
345 | SWIFT_VERSION = "5.0";
346 | };
347 | name = "Debug";
348 | };
349 | "OBJ_34" = {
350 | isa = "XCBuildConfiguration";
351 | buildSettings = {
352 | LD = "/usr/bin/true";
353 | OTHER_SWIFT_FLAGS = (
354 | "-swift-version",
355 | "5",
356 | "-I",
357 | "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2",
358 | "-sdk",
359 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk",
360 | "-package-description-version",
361 | "5.3.0"
362 | );
363 | SWIFT_VERSION = "5.0";
364 | };
365 | name = "Release";
366 | };
367 | "OBJ_35" = {
368 | isa = "PBXSourcesBuildPhase";
369 | files = (
370 | "OBJ_36"
371 | );
372 | };
373 | "OBJ_36" = {
374 | isa = "PBXBuildFile";
375 | fileRef = "OBJ_6";
376 | };
377 | "OBJ_38" = {
378 | isa = "XCConfigurationList";
379 | buildConfigurations = (
380 | "OBJ_39",
381 | "OBJ_40"
382 | );
383 | defaultConfigurationIsVisible = "0";
384 | defaultConfigurationName = "Release";
385 | };
386 | "OBJ_39" = {
387 | isa = "XCBuildConfiguration";
388 | buildSettings = {
389 | };
390 | name = "Debug";
391 | };
392 | "OBJ_4" = {
393 | isa = "XCBuildConfiguration";
394 | buildSettings = {
395 | CLANG_ENABLE_OBJC_ARC = "YES";
396 | COMBINE_HIDPI_IMAGES = "YES";
397 | COPY_PHASE_STRIP = "YES";
398 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
399 | DYLIB_INSTALL_NAME_BASE = "@rpath";
400 | GCC_OPTIMIZATION_LEVEL = "s";
401 | GCC_PREPROCESSOR_DEFINITIONS = (
402 | "$(inherited)",
403 | "SWIFT_PACKAGE=1"
404 | );
405 | MACOSX_DEPLOYMENT_TARGET = "10.10";
406 | OTHER_SWIFT_FLAGS = (
407 | "$(inherited)",
408 | "-DXcode"
409 | );
410 | PRODUCT_NAME = "$(TARGET_NAME)";
411 | SDKROOT = "macosx";
412 | SUPPORTED_PLATFORMS = (
413 | "macosx",
414 | "iphoneos",
415 | "iphonesimulator",
416 | "appletvos",
417 | "appletvsimulator",
418 | "watchos",
419 | "watchsimulator"
420 | );
421 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
422 | "$(inherited)",
423 | "SWIFT_PACKAGE"
424 | );
425 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
426 | USE_HEADERMAP = "NO";
427 | };
428 | name = "Release";
429 | };
430 | "OBJ_40" = {
431 | isa = "XCBuildConfiguration";
432 | buildSettings = {
433 | };
434 | name = "Release";
435 | };
436 | "OBJ_41" = {
437 | isa = "PBXTargetDependency";
438 | target = "BxRefreshableScrollView::BxRefreshableScrollViewTests";
439 | };
440 | "OBJ_43" = {
441 | isa = "XCConfigurationList";
442 | buildConfigurations = (
443 | "OBJ_44",
444 | "OBJ_45"
445 | );
446 | defaultConfigurationIsVisible = "0";
447 | defaultConfigurationName = "Release";
448 | };
449 | "OBJ_44" = {
450 | isa = "XCBuildConfiguration";
451 | buildSettings = {
452 | CLANG_ENABLE_MODULES = "YES";
453 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES";
454 | FRAMEWORK_SEARCH_PATHS = (
455 | "$(inherited)",
456 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
457 | );
458 | HEADER_SEARCH_PATHS = (
459 | "$(inherited)"
460 | );
461 | INFOPLIST_FILE = "BxRefreshableScrollView.xcodeproj/BxRefreshableScrollViewTests_Info.plist";
462 | IPHONEOS_DEPLOYMENT_TARGET = "14.0";
463 | LD_RUNPATH_SEARCH_PATHS = (
464 | "$(inherited)",
465 | "@loader_path/../Frameworks",
466 | "@loader_path/Frameworks"
467 | );
468 | MACOSX_DEPLOYMENT_TARGET = "10.15";
469 | OTHER_CFLAGS = (
470 | "$(inherited)"
471 | );
472 | OTHER_LDFLAGS = (
473 | "$(inherited)"
474 | );
475 | OTHER_SWIFT_FLAGS = (
476 | "$(inherited)"
477 | );
478 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
479 | "$(inherited)"
480 | );
481 | SWIFT_VERSION = "5.0";
482 | TARGET_NAME = "BxRefreshableScrollViewTests";
483 | TVOS_DEPLOYMENT_TARGET = "9.0";
484 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
485 | };
486 | name = "Debug";
487 | };
488 | "OBJ_45" = {
489 | isa = "XCBuildConfiguration";
490 | buildSettings = {
491 | CLANG_ENABLE_MODULES = "YES";
492 | EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES";
493 | FRAMEWORK_SEARCH_PATHS = (
494 | "$(inherited)",
495 | "$(PLATFORM_DIR)/Developer/Library/Frameworks"
496 | );
497 | HEADER_SEARCH_PATHS = (
498 | "$(inherited)"
499 | );
500 | INFOPLIST_FILE = "BxRefreshableScrollView.xcodeproj/BxRefreshableScrollViewTests_Info.plist";
501 | IPHONEOS_DEPLOYMENT_TARGET = "14.0";
502 | LD_RUNPATH_SEARCH_PATHS = (
503 | "$(inherited)",
504 | "@loader_path/../Frameworks",
505 | "@loader_path/Frameworks"
506 | );
507 | MACOSX_DEPLOYMENT_TARGET = "10.15";
508 | OTHER_CFLAGS = (
509 | "$(inherited)"
510 | );
511 | OTHER_LDFLAGS = (
512 | "$(inherited)"
513 | );
514 | OTHER_SWIFT_FLAGS = (
515 | "$(inherited)"
516 | );
517 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
518 | "$(inherited)"
519 | );
520 | SWIFT_VERSION = "5.0";
521 | TARGET_NAME = "BxRefreshableScrollViewTests";
522 | TVOS_DEPLOYMENT_TARGET = "9.0";
523 | WATCHOS_DEPLOYMENT_TARGET = "2.0";
524 | };
525 | name = "Release";
526 | };
527 | "OBJ_46" = {
528 | isa = "PBXSourcesBuildPhase";
529 | files = (
530 | "OBJ_47",
531 | "OBJ_48"
532 | );
533 | };
534 | "OBJ_47" = {
535 | isa = "PBXBuildFile";
536 | fileRef = "OBJ_16";
537 | };
538 | "OBJ_48" = {
539 | isa = "PBXBuildFile";
540 | fileRef = "OBJ_17";
541 | };
542 | "OBJ_49" = {
543 | isa = "PBXFrameworksBuildPhase";
544 | files = (
545 | "OBJ_50"
546 | );
547 | };
548 | "OBJ_5" = {
549 | isa = "PBXGroup";
550 | children = (
551 | "OBJ_6",
552 | "OBJ_7",
553 | "OBJ_14",
554 | "OBJ_18",
555 | "OBJ_21"
556 | );
557 | path = "";
558 | sourceTree = "";
559 | };
560 | "OBJ_50" = {
561 | isa = "PBXBuildFile";
562 | fileRef = "BxRefreshableScrollView::BxRefreshableScrollView::Product";
563 | };
564 | "OBJ_51" = {
565 | isa = "PBXTargetDependency";
566 | target = "BxRefreshableScrollView::BxRefreshableScrollView";
567 | };
568 | "OBJ_6" = {
569 | isa = "PBXFileReference";
570 | explicitFileType = "sourcecode.swift";
571 | path = "Package.swift";
572 | sourceTree = "";
573 | };
574 | "OBJ_7" = {
575 | isa = "PBXGroup";
576 | children = (
577 | "OBJ_8"
578 | );
579 | name = "Sources";
580 | path = "";
581 | sourceTree = "SOURCE_ROOT";
582 | };
583 | "OBJ_8" = {
584 | isa = "PBXGroup";
585 | children = (
586 | "OBJ_9",
587 | "OBJ_10",
588 | "OBJ_11",
589 | "OBJ_12",
590 | "OBJ_13"
591 | );
592 | name = "BxRefreshableScrollView";
593 | path = "Sources/BxRefreshableScrollView";
594 | sourceTree = "SOURCE_ROOT";
595 | };
596 | "OBJ_9" = {
597 | isa = "PBXFileReference";
598 | path = "BxRefreshableScrollView.h";
599 | sourceTree = "";
600 | };
601 | };
602 | rootObject = "OBJ_1";
603 | }
604 |
--------------------------------------------------------------------------------