├── promo.png
├── CombineMarble
├── Resources
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ └── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
├── CombineMarble.entitlements
├── Combines
│ ├── CombineSectionContainer.swift
│ ├── Map
│ │ └── CombineMapSectionContainer.swift
│ ├── Filter
│ │ └── CombineFilterSectionContainer.swift
│ ├── Merge
│ │ └── CombineMergeSectionContainer.swift
│ ├── CombineLatest
│ │ └── CombineLatestSectionContainer.swift
│ └── Zip
│ │ └── CombineZipSectionContainer.swift
├── Views
│ ├── LineDecorationView.swift
│ ├── SectionHeaderView.swift
│ ├── LineCell.swift
│ ├── LineDecorationView.xib
│ ├── SectionHeaderView.xib
│ └── LineCell.xib
├── AppDelegate.swift
├── Model
│ └── SectionController.swift
├── Info.plist
├── SceneDelegate.swift
└── ViewController.swift
├── CombineMarble.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── alfianlosari.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── alfianlosari.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
└── README.md
/promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfianlosari/AppleCombineMarbleVisualizer/HEAD/promo.png
--------------------------------------------------------------------------------
/CombineMarble/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/xcuserdata/alfianlosari.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/project.xcworkspace/xcuserdata/alfianlosari.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfianlosari/AppleCombineMarbleVisualizer/HEAD/CombineMarble.xcodeproj/project.xcworkspace/xcuserdata/alfianlosari.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Combine Framework Marble Diagram Visualizer App
2 |
3 | 
4 |
5 | Apple Combine Framework Marble Diagram Visualizer App
6 |
7 | ## Requirements
8 | - macOS 10.15 Catalina
9 | - Xcode 11 Beta
10 | - iOS 13
11 |
12 | ## Getting Started
13 | - Clone the Repository
14 | - Build and Run the project
--------------------------------------------------------------------------------
/CombineMarble/CombineMarble.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/CombineSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Combine
10 |
11 | protocol CombineSectionContainer {
12 | var sections: [SectionController.CombineCollection] { get }
13 | var isCombined: Bool { get }
14 | func reset()
15 | func send()
16 | }
17 |
--------------------------------------------------------------------------------
/CombineMarble/Views/LineDecorationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LineDecorationView.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LineDecorationView: UICollectionReusableView {
12 |
13 | override func awakeFromNib() {
14 | super.awakeFromNib()
15 | // Initialization code
16 | }
17 |
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/xcuserdata/alfianlosari.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | CombineMarble.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CombineMarble/Views/SectionHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionHeaderView.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SectionHeaderView: UICollectionReusableView {
12 |
13 | @IBOutlet weak var label: UILabel!
14 |
15 | override func awakeFromNib() {
16 | super.awakeFromNib()
17 | // Initialization code
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/CombineMarble/Views/LineCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LineCell.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LineCell: UICollectionViewCell {
12 |
13 | @IBOutlet weak var view: UIView!
14 | @IBOutlet weak var viewHeightConstraint: NSLayoutConstraint!
15 | @IBOutlet weak var label: UILabel!
16 |
17 | override func layoutSubviews() {
18 | super.layoutSubviews()
19 | let length = min(self.bounds.height, self.bounds.width) - 8.0
20 | view.layer.cornerRadius = length / 2.0
21 | viewHeightConstraint.constant = length
22 | }
23 |
24 | func setup() {
25 | view.layer.cornerRadius = view.frame.width / 2.0
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/CombineMarble/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | // Override point for customization after application launch.
16 | return true
17 | }
18 |
19 | func applicationWillTerminate(_ application: UIApplication) {
20 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
21 | }
22 |
23 | // MARK: UISceneSession Lifecycle
24 |
25 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
26 | // Called when a new scene session is being created.
27 | // Use this method to select a configuration to create the new scene with.
28 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
29 | }
30 |
31 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
32 | // Called when the user discards a scene session.
33 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
34 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
35 | }
36 |
37 |
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/CombineMarble/Resources/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/CombineMarble/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/CombineMarble/Model/SectionController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionController.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Combine
11 |
12 | let combineDidChangeNotification = Notification.Name(rawValue: "CombineDidChangeNotification")
13 |
14 | class SectionController {
15 |
16 | fileprivate var _collections = [CombineSectionContainer]()
17 | var collections: [CombineSectionContainer] {
18 | return _collections
19 | }
20 |
21 | struct CombineItem: Hashable {
22 | let text: String?
23 |
24 | let identifier = UUID()
25 | func hash(into hasher: inout Hasher) {
26 | hasher.combine(identifier)
27 | }
28 | }
29 |
30 | struct CombineCollection: Hashable {
31 |
32 | let title: String?
33 | var items: [CombineItem]
34 | var container: CombineSectionContainer? = nil
35 |
36 | var isCombined = false
37 |
38 | let identifier = UUID()
39 | func hash(into hasher: inout Hasher) {
40 | hasher.combine(identifier)
41 | }
42 |
43 | static func == (lhs: SectionController.CombineCollection, rhs: SectionController.CombineCollection) -> Bool {
44 | return lhs.identifier == rhs.identifier
45 | }
46 | }
47 |
48 | init() {
49 | generateCollections()
50 | }
51 | }
52 |
53 |
54 | extension SectionController {
55 |
56 | func generateCollections() {
57 |
58 | let map = CombineMapSectionContainer()
59 | let combineLatest = CombineLatestSectionContainer()
60 | let merge = CombineMergeSectionContainer()
61 | let zip = CombineZipSectionContainer()
62 | let filter = CombineFilterSectionContainer()
63 |
64 | _collections = [
65 | zip,
66 | combineLatest,
67 | merge,
68 | map,
69 | filter
70 | ]
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/CombineMarble/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UILaunchStoryboardName
33 | LaunchScreen
34 | UISceneConfigurationName
35 | Default Configuration
36 | UISceneDelegateClassName
37 | $(PRODUCT_MODULE_NAME).SceneDelegate
38 | UISceneStoryboardFile
39 | Main
40 |
41 |
42 |
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/CombineMarble/Views/LineDecorationView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/CombineMarble/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/Map/CombineMapSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineMapSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Combine
10 | import Foundation
11 |
12 | class CombineMapSectionContainer: CombineSectionContainer {
13 |
14 | var isCombined: Bool = false
15 | let numbers = PassthroughSubject()
16 |
17 | var sections: [SectionController.CombineCollection] {
18 | return [
19 | firstLine,
20 | mappedLine
21 | ]
22 | }
23 |
24 | private lazy var firstLine: SectionController.CombineCollection = {
25 | var first = SectionController.CombineCollection(title: "Map", items: [])
26 | first.container = self
27 |
28 | return first
29 | }()
30 |
31 | private lazy var mappedLine: SectionController.CombineCollection = {
32 | var second = SectionController.CombineCollection(title: " ", items: [])
33 | second.container = self
34 | return second
35 | }()
36 |
37 |
38 | private lazy var emojis: [String] = {
39 | return self.randomEmojis
40 | }()
41 |
42 | private var randomValues: [Int] {
43 | return Array(0..<8).shuffled()
44 | }
45 |
46 | private lazy var sendValues: [Int] = {
47 | return self.randomValues
48 | }()
49 |
50 | private lazy var randomEmojis: [String] = {
51 | return ["🥰", "😍", "😜", "🤪", "😉", "😄", "😀", "🤓"].shuffled()
52 | }()
53 |
54 | init() {
55 | _ = numbers.sink(receiveValue: { (value) in
56 | self.firstLine.items.append(SectionController.CombineItem(text: "\(value)"))
57 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
58 | })
59 |
60 | _ = numbers.map {
61 | self.emojis[$0]
62 | }.sink(receiveValue: { (emoji) in
63 | self.mappedLine.items.append(SectionController.CombineItem(text: "\(emoji)"))
64 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.mappedLine)
65 | })
66 | }
67 |
68 | func send() {
69 | guard let value = sendValues.popLast() else {
70 | self.isCombined = true
71 | return
72 | }
73 | numbers.send(value)
74 | }
75 |
76 | func reset() {
77 | sendValues = self.randomValues
78 | emojis = self.randomEmojis
79 | self.isCombined = false
80 | self.firstLine.items.removeAll()
81 | self.mappedLine.items.removeAll()
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/Filter/CombineFilterSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineFilterSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Combine
11 |
12 | class CombineFilterSectionContainer: CombineSectionContainer {
13 |
14 | var isCombined: Bool = false
15 | let numbers = PassthroughSubject()
16 |
17 | var sections: [SectionController.CombineCollection] {
18 | return [
19 | firstLine,
20 | mappedLine
21 | ]
22 | }
23 |
24 | private lazy var firstLine: SectionController.CombineCollection = {
25 | var first = SectionController.CombineCollection(title: "Filter (is even number)", items: [])
26 | first.container = self
27 |
28 | return first
29 | }()
30 |
31 | private lazy var mappedLine: SectionController.CombineCollection = {
32 | var second = SectionController.CombineCollection(title: " ", items: [])
33 | second.container = self
34 | return second
35 | }()
36 |
37 | private var randomValues: [Int] {
38 | return Array(0..<10).shuffled()
39 | }
40 |
41 | private lazy var sendValues: [Int] = {
42 | return self.randomValues
43 | }()
44 |
45 | init() {
46 | _ = numbers.sink(receiveValue: { (value) in
47 | self.firstLine.items.append(SectionController.CombineItem(text: "\(value)"))
48 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
49 | })
50 |
51 | _ = numbers
52 | .filter { $0 % 2 != 0}
53 | .sink(receiveValue: { (value) in
54 | self.mappedLine.items.append(SectionController.CombineItem(text: nil))
55 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.mappedLine)
56 | })
57 |
58 | _ = numbers
59 | .filter { $0 % 2 == 0}
60 | .sink(receiveValue: { (value) in
61 | self.mappedLine.items.append(SectionController.CombineItem(text: "\(value)"))
62 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.mappedLine)
63 | })
64 | }
65 |
66 | func send() {
67 | guard let value = sendValues.popLast() else {
68 | self.isCombined = true
69 | return
70 | }
71 | numbers.send(value)
72 | }
73 |
74 | func reset() {
75 | sendValues = self.randomValues
76 | self.isCombined = false
77 | self.firstLine.items.removeAll()
78 | self.mappedLine.items.removeAll()
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/CombineMarble/Resources/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/Merge/CombineMergeSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineMergeSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Combine
11 |
12 | class CombineMergeSectionContainer: CombineSectionContainer {
13 |
14 | var numbers1 = PassthroughSubject()
15 | var numbers2 = PassthroughSubject()
16 |
17 | var sections: [SectionController.CombineCollection] {
18 | return [
19 | firstLine,
20 | secondLine,
21 | combinedLine
22 | ]
23 | }
24 |
25 | private lazy var firstLine: SectionController.CombineCollection = {
26 | var first = SectionController.CombineCollection(title: "Merge", items: [])
27 | first.container = self
28 | return first
29 | }()
30 |
31 | private lazy var secondLine: SectionController.CombineCollection = {
32 | var second = SectionController.CombineCollection(title: " ", items: [])
33 | second.container = self
34 | return second
35 | }()
36 |
37 | private lazy var combinedLine: SectionController.CombineCollection = {
38 | var second = SectionController.CombineCollection(title: " ", items: [])
39 | second.container = self
40 | return second
41 | }()
42 |
43 | private var randomValues: [String] {
44 | return [
45 | "1",
46 | "D",
47 | "3",
48 | "7",
49 | "B",
50 | "C",
51 | "9",
52 | "F"
53 | ].shuffled()
54 |
55 | }
56 |
57 | private lazy var sendValues: [String] = {
58 | return self.randomValues
59 | }()
60 |
61 | var isCombined = false
62 |
63 | init() {
64 | setupSubscription()
65 | }
66 |
67 | private func setupSubscription() {
68 | _ = numbers1.sink(receiveValue: { (value) in
69 | self.firstLine.items.append(SectionController.CombineItem(text: value))
70 | self.secondLine.items.append(SectionController.CombineItem(text: nil))
71 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
72 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
73 | })
74 |
75 | _ = numbers2.sink(receiveValue: { (value) in
76 | self.firstLine.items.append(SectionController.CombineItem(text: nil))
77 | self.secondLine.items.append(SectionController.CombineItem(text: value))
78 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
79 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
80 | })
81 |
82 | _ = numbers1.merge(with: numbers2)
83 | .sink(receiveValue: { (merged) in
84 | self.combinedLine.items.append(SectionController.CombineItem(text: merged))
85 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
86 | })
87 | }
88 |
89 | func reset() {
90 | sendValues = self.randomValues
91 |
92 | self.isCombined = false
93 |
94 | self.firstLine.items.removeAll()
95 | self.secondLine.items.removeAll()
96 | self.combinedLine.items.removeAll()
97 |
98 | numbers1 = PassthroughSubject()
99 | numbers2 = PassthroughSubject()
100 |
101 | setupSubscription()
102 | }
103 |
104 | func send() {
105 | guard let value = sendValues.popLast() else {
106 | self.isCombined = true
107 | return
108 | }
109 |
110 | if let _ = Int(value) {
111 | numbers1.send(value)
112 |
113 | } else {
114 | numbers2.send(value)
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/CombineMarble/Views/SectionHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/CombineLatest/CombineLatestSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineLatestSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Combine
10 | import Foundation
11 |
12 | class CombineLatestSectionContainer: CombineSectionContainer {
13 |
14 | var isCombined = false
15 | var sections: [SectionController.CombineCollection] {
16 | return [
17 | firstLine,
18 | secondLine,
19 | combinedLine
20 | ]
21 | }
22 | var numbers1 = PassthroughSubject()
23 | var numbers2 = PassthroughSubject()
24 |
25 | private lazy var firstLine: SectionController.CombineCollection = {
26 | var first = SectionController.CombineCollection(title: "Combine Latest", items: [])
27 | first.container = self
28 | return first
29 | }()
30 |
31 | private lazy var secondLine: SectionController.CombineCollection = {
32 | var second = SectionController.CombineCollection(title: " ", items: [])
33 | second.container = self
34 | return second
35 | }()
36 |
37 | private lazy var combinedLine: SectionController.CombineCollection = {
38 | var second = SectionController.CombineCollection(title: " ", items: [])
39 | second.container = self
40 | return second
41 | }()
42 |
43 | var currentFirstLine: String?
44 | var currentSecondLine: String?
45 |
46 | var isLineCombined: Bool {
47 | return currentFirstLine != nil && currentSecondLine != nil
48 | }
49 |
50 | private var randomValues: [String] {
51 | return [
52 | "1",
53 | "D",
54 | "3",
55 | "7",
56 | "B",
57 | "C",
58 | "9",
59 | "F"
60 | ].shuffled()
61 | }
62 |
63 | private lazy var sendValues: [String] = {
64 | return self.randomValues
65 | }()
66 |
67 | private func setupSubscription() {
68 | _ = numbers1.sink(receiveValue: { (value) in
69 | self.firstLine.items.append(SectionController.CombineItem(text: value))
70 | self.secondLine.items.append(SectionController.CombineItem(text: nil))
71 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
72 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
73 | if !self.isLineCombined {
74 | self.combinedLine.items.append(SectionController.CombineItem(text: nil))
75 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
76 | }
77 | })
78 |
79 | _ = numbers2.sink(receiveValue: { (value) in
80 | self.firstLine.items.append(SectionController.CombineItem(text: nil))
81 | self.secondLine.items.append(SectionController.CombineItem(text: value))
82 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
83 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
84 | if !self.isLineCombined {
85 | self.combinedLine.items.append(SectionController.CombineItem(text: nil))
86 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
87 | }
88 | })
89 |
90 | _ = numbers1.combineLatest(numbers2) { "\($0 ?? "")\($1 ?? "")" }
91 | .sink { combined in
92 |
93 | self.combinedLine.items.append(SectionController.CombineItem(text: combined))
94 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
95 | }
96 | }
97 |
98 | init() {
99 | setupSubscription()
100 | }
101 |
102 | func reset() {
103 | sendValues = self.randomValues
104 |
105 | self.isCombined = false
106 | currentFirstLine = nil
107 | currentSecondLine = nil
108 |
109 | self.firstLine.items.removeAll()
110 | self.secondLine.items.removeAll()
111 | self.combinedLine.items.removeAll()
112 |
113 | numbers1 = PassthroughSubject()
114 | numbers2 = PassthroughSubject()
115 |
116 | setupSubscription()
117 | }
118 |
119 | func send() {
120 | guard let value = sendValues.popLast() else {
121 | self.isCombined = true
122 | return
123 | }
124 |
125 | if let _ = Int(value) {
126 | currentFirstLine = value
127 | numbers1.send(value)
128 |
129 | } else {
130 | currentSecondLine = value
131 | numbers2.send(value)
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/CombineMarble/Combines/Zip/CombineZipSectionContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineZipSectionContainer.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 04/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Combine
10 | import Foundation
11 |
12 | class CombineZipSectionContainer: CombineSectionContainer {
13 |
14 | var isCombined = false
15 | var numbers1 = PassthroughSubject()
16 | var numbers2 = PassthroughSubject()
17 | var currentFirstLine: [String] = []
18 | var currentSecondLine: [String] = []
19 |
20 | var isLineCombined: Bool {
21 | return !currentFirstLine.isEmpty && !currentSecondLine.isEmpty
22 | }
23 |
24 | var sections: [SectionController.CombineCollection] {
25 | return [
26 | firstLine,
27 | secondLine,
28 | combinedLine
29 | ]
30 | }
31 |
32 | private lazy var firstLine: SectionController.CombineCollection = {
33 | var first = SectionController.CombineCollection(title: "Zip", items: [])
34 | first.container = self
35 | return first
36 | }()
37 |
38 | private lazy var secondLine: SectionController.CombineCollection = {
39 | var second = SectionController.CombineCollection(title: " ", items: [])
40 | second.container = self
41 | return second
42 | }()
43 |
44 | private lazy var combinedLine: SectionController.CombineCollection = {
45 | var second = SectionController.CombineCollection(title: " ", items: [])
46 | second.container = self
47 | return second
48 | }()
49 |
50 | private var randomValues: [String] {
51 | return [
52 | "1",
53 | "D",
54 | "3",
55 | "7",
56 | "B",
57 | "C",
58 | "9",
59 | "F"
60 | ].shuffled()
61 | }
62 |
63 | private lazy var sendValues: [String] = {
64 | return self.randomValues
65 | }()
66 |
67 | private func setupSubscription() {
68 | _ = numbers1.sink(receiveValue: { (value) in
69 | self.firstLine.items.append(SectionController.CombineItem(text: value))
70 | self.secondLine.items.append(SectionController.CombineItem(text: nil))
71 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
72 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
73 | if !self.isLineCombined {
74 | self.combinedLine.items.append(SectionController.CombineItem(text: nil))
75 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
76 | }
77 | })
78 |
79 | _ = numbers2.sink(receiveValue: { (value) in
80 | self.firstLine.items.append(SectionController.CombineItem(text: nil))
81 | self.secondLine.items.append(SectionController.CombineItem(text: value))
82 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.firstLine)
83 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.secondLine)
84 | if !self.isLineCombined {
85 | self.combinedLine.items.append(SectionController.CombineItem(text: nil))
86 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
87 | }
88 | })
89 |
90 | _ = numbers1.zip(numbers2) { "\($0 ?? "")\($1 ?? "")" }
91 | .sink { combined in
92 | _ = self.currentFirstLine.popLast()
93 | _ = self.currentSecondLine.popLast()
94 | self.combinedLine.items.append(SectionController.CombineItem(text: combined))
95 | NotificationCenter.default.post(name: combineDidChangeNotification, object: self.combinedLine)
96 | }
97 | }
98 |
99 | init() {
100 | setupSubscription()
101 | }
102 |
103 | func reset() {
104 | sendValues = self.randomValues
105 |
106 | self.isCombined = false
107 |
108 | currentFirstLine = []
109 | currentSecondLine = []
110 |
111 | self.firstLine.items.removeAll()
112 | self.secondLine.items.removeAll()
113 | self.combinedLine.items.removeAll()
114 |
115 | numbers1 = PassthroughSubject()
116 | numbers2 = PassthroughSubject()
117 |
118 | setupSubscription()
119 | }
120 |
121 | func send() {
122 | guard let value = sendValues.popLast() else {
123 | self.isCombined = true
124 | return
125 | }
126 |
127 | if let _ = Int(value) {
128 | currentFirstLine.append(value)
129 | numbers1.send(value)
130 |
131 | } else {
132 | currentSecondLine.append(value)
133 | numbers2.send(value)
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/CombineMarble/Views/LineCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/CombineMarble/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // CombineMarble
4 | //
5 | // Created by Alfian Losari on 02/07/19.
6 | // Copyright © 2019 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Combine
11 |
12 | class ViewController: UIViewController {
13 |
14 | var colors: [UIColor] {
15 | return [
16 | UIColor.systemRed,
17 | UIColor.systemBlue,
18 | UIColor.systemPink,
19 | UIColor.systemTeal,
20 | UIColor.systemGreen,
21 | UIColor.systemIndigo,
22 | UIColor.systemYellow,
23 | UIColor.systemPurple,
24 | UIColor.systemOrange,
25 | UIColor.systemRed
26 | ].shuffled()
27 | }
28 |
29 | var isCombining = false
30 |
31 | let sectionController = SectionController()
32 | static let lineDecorationElementKind = "line-decoration-element-kind"
33 | static let sectionHeaderElementKind = "sectionHeaderElementKind"
34 |
35 | var collectionView: UICollectionView! = nil
36 | var dataSource: UICollectionViewDiffableDataSource! = nil
37 |
38 | override func viewDidLoad() {
39 | super.viewDidLoad()
40 | navigationItem.title = " Combine Visualizer"
41 |
42 | configureHierarchy()
43 | configureDataSource()
44 | configureCombineNotificationUpdateSubscription()
45 |
46 | configureNavItem()
47 | toggleCombine()
48 | }
49 |
50 | private func configureCombineNotificationUpdateSubscription() {
51 | _ = NotificationCenter.default.publisher(for: combineDidChangeNotification)
52 | .sink { (note) in
53 | guard let section = note.object as? SectionController.CombineCollection else {
54 | return
55 | }
56 |
57 | let snapshot = self.dataSource.snapshot()
58 | guard let _ = snapshot.indexOfSection(section) else {
59 | return
60 | }
61 | let items = section.items
62 | snapshot.deleteItems(items)
63 | snapshot.appendItems(items, toSection: section)
64 |
65 | self.dataSource.apply(snapshot, animatingDifferences: true)
66 | }
67 | }
68 |
69 | private func configureHierarchy() {
70 | collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
71 | collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
72 | collectionView.backgroundColor = .systemBackground
73 | collectionView.register(UINib(nibName: "LineCell", bundle: nil), forCellWithReuseIdentifier: "LineCell")
74 | collectionView.register(
75 | UINib(nibName: "SectionHeaderView", bundle: nil),
76 | forSupplementaryViewOfKind: ViewController.sectionHeaderElementKind,
77 | withReuseIdentifier: "SectionHeaderView")
78 | view.addSubview(collectionView)
79 | }
80 |
81 | private func configureDataSource() {
82 | dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) {
83 | (collectionView: UICollectionView, indexPath: IndexPath, item: SectionController.CombineItem) -> UICollectionViewCell? in
84 | guard let cell = collectionView.dequeueReusableCell(
85 | withReuseIdentifier: "LineCell",
86 | for: indexPath) as? LineCell else { fatalError("Cannot create new cell") }
87 | let sections = self.sectionController.collections.flatMap { $0.sections }
88 | let text = sections[indexPath.section].items[indexPath.item].text
89 |
90 | cell.label.text = text
91 | cell.view.isHidden = text == nil
92 | cell.view.backgroundColor = self.colors[indexPath.item % 10]
93 |
94 | return cell
95 | }
96 |
97 | dataSource.supplementaryViewProvider = { (
98 | collectionView: UICollectionView,
99 | kind: String,
100 | indexPath: IndexPath) -> UICollectionReusableView? in
101 |
102 | guard let supplementaryView = collectionView.dequeueReusableSupplementaryView(
103 | ofKind: kind,
104 | withReuseIdentifier: "SectionHeaderView",
105 | for: indexPath) as? SectionHeaderView else { fatalError("Cannot create new supplementary") }
106 |
107 | let sections = self.sectionController.collections.flatMap { $0.sections }
108 |
109 | supplementaryView.label.text = sections[indexPath.section].title
110 | return supplementaryView
111 | }
112 | dataSource.apply(getSnapshot(), animatingDifferences: false)
113 | }
114 |
115 | func getSnapshot() -> NSDiffableDataSourceSnapshot {
116 | let snapshot = NSDiffableDataSourceSnapshot()
117 | sectionController.collections.forEach {
118 | for section in $0.sections {
119 | snapshot.appendSections([section])
120 | snapshot.appendItems(section.items)
121 | }
122 | }
123 | return snapshot
124 | }
125 |
126 | func performCombine(section: CombineSectionContainer) {
127 | if !isCombining {
128 | return
129 | }
130 |
131 | section.send()
132 | let delay = 1000
133 | DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(delay)) {
134 | if section.isCombined {
135 | let snapshot = self.dataSource.snapshot()
136 | section.sections.forEach { (section) in
137 | snapshot.deleteItems(section.items)
138 | }
139 | self.dataSource.apply(snapshot, animatingDifferences: true)
140 | section.reset()
141 | }
142 | self.performCombine(section: section)
143 | }
144 | }
145 |
146 | func performCombine() {
147 | self.sectionController.collections.forEach { performCombine(section: $0) }
148 | }
149 |
150 | private func createLayout() -> UICollectionViewLayout {
151 | let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.125),
152 | heightDimension: .fractionalHeight(1.0))
153 | let item = NSCollectionLayoutItem(layoutSize: itemSize)
154 |
155 | let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
156 | heightDimension: .absolute(44))
157 |
158 | let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
159 | subitems: [item])
160 |
161 | let section = NSCollectionLayoutSection(group: group)
162 | section.interGroupSpacing = 0
163 | section.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0)
164 | section.orthogonalScrollingBehavior = .continuous
165 |
166 | let sectionBackgroundDecoration = NSCollectionLayoutDecorationItem.background(
167 | elementKind: ViewController.lineDecorationElementKind)
168 | sectionBackgroundDecoration.contentInsets = NSDirectionalEdgeInsets(top: 44, leading: 0, bottom: 0, trailing: 0)
169 | section.decorationItems = [sectionBackgroundDecoration]
170 | let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
171 | heightDimension: .estimated(44))
172 |
173 | let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
174 | layoutSize: headerFooterSize,
175 | elementKind: ViewController.sectionHeaderElementKind, alignment: .top)
176 |
177 | section.boundarySupplementaryItems = [sectionHeader]
178 |
179 | let layout = UICollectionViewCompositionalLayout(section: section)
180 | layout.register(
181 | UINib(nibName: "LineDecorationView", bundle: nil),
182 | forDecorationViewOfKind: ViewController.lineDecorationElementKind)
183 | return layout
184 | }
185 |
186 | func configureNavItem() {
187 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: isCombining ? "Pause" : "Combine",
188 | style: .plain, target: self,
189 | action: #selector(toggleCombine))
190 | }
191 |
192 | @objc
193 | func toggleCombine() {
194 | isCombining.toggle()
195 | if isCombining {
196 | performCombine()
197 | }
198 | configureNavItem()
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/CombineMarble.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8B184E6522CE22EF009F5EF7 /* CombineSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E6422CE22EF009F5EF7 /* CombineSectionContainer.swift */; };
11 | 8B184E6822CE2318009F5EF7 /* CombineLatestSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E6722CE2318009F5EF7 /* CombineLatestSectionContainer.swift */; };
12 | 8B184E6B22CE234B009F5EF7 /* CombineMapSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E6A22CE234B009F5EF7 /* CombineMapSectionContainer.swift */; };
13 | 8B184E6E22CE25BD009F5EF7 /* CombineMergeSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E6D22CE25BD009F5EF7 /* CombineMergeSectionContainer.swift */; };
14 | 8B184E7122CE2C89009F5EF7 /* CombineZipSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E7022CE2C89009F5EF7 /* CombineZipSectionContainer.swift */; };
15 | 8B184E7422CE34F1009F5EF7 /* CombineFilterSectionContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B184E7322CE34F1009F5EF7 /* CombineFilterSectionContainer.swift */; };
16 | 8B23C11922CB7F49002C33D5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C11822CB7F49002C33D5 /* AppDelegate.swift */; };
17 | 8B23C11B22CB7F49002C33D5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C11A22CB7F49002C33D5 /* SceneDelegate.swift */; };
18 | 8B23C11D22CB7F49002C33D5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C11C22CB7F49002C33D5 /* ViewController.swift */; };
19 | 8B23C12022CB7F49002C33D5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C11E22CB7F49002C33D5 /* Main.storyboard */; };
20 | 8B23C12222CB7F4B002C33D5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C12122CB7F4B002C33D5 /* Assets.xcassets */; };
21 | 8B23C12522CB7F4B002C33D5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C12322CB7F4B002C33D5 /* LaunchScreen.storyboard */; };
22 | 8B23C12E22CB9857002C33D5 /* LineCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C12C22CB9857002C33D5 /* LineCell.swift */; };
23 | 8B23C12F22CB9857002C33D5 /* LineCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C12D22CB9857002C33D5 /* LineCell.xib */; };
24 | 8B23C13222CBA2A1002C33D5 /* LineDecorationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C13022CBA2A1002C33D5 /* LineDecorationView.swift */; };
25 | 8B23C13322CBA2A1002C33D5 /* LineDecorationView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C13122CBA2A1002C33D5 /* LineDecorationView.xib */; };
26 | 8B23C13522CBAD50002C33D5 /* SectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C13422CBAD50002C33D5 /* SectionController.swift */; };
27 | 8B23C13A22CBB52E002C33D5 /* SectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B23C13822CBB52E002C33D5 /* SectionHeaderView.swift */; };
28 | 8B23C13B22CBB52E002C33D5 /* SectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B23C13922CBB52E002C33D5 /* SectionHeaderView.xib */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXFileReference section */
32 | 8B184E6422CE22EF009F5EF7 /* CombineSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineSectionContainer.swift; sourceTree = ""; };
33 | 8B184E6722CE2318009F5EF7 /* CombineLatestSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineLatestSectionContainer.swift; sourceTree = ""; };
34 | 8B184E6A22CE234B009F5EF7 /* CombineMapSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineMapSectionContainer.swift; sourceTree = ""; };
35 | 8B184E6D22CE25BD009F5EF7 /* CombineMergeSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineMergeSectionContainer.swift; sourceTree = ""; };
36 | 8B184E7022CE2C89009F5EF7 /* CombineZipSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineZipSectionContainer.swift; sourceTree = ""; };
37 | 8B184E7322CE34F1009F5EF7 /* CombineFilterSectionContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineFilterSectionContainer.swift; sourceTree = ""; };
38 | 8B184E7922CE50DD009F5EF7 /* CombineMarble.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CombineMarble.entitlements; sourceTree = ""; };
39 | 8B23C11522CB7F49002C33D5 /* Combine Visualizer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = " Combine Visualizer.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40 | 8B23C11822CB7F49002C33D5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
41 | 8B23C11A22CB7F49002C33D5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
42 | 8B23C11C22CB7F49002C33D5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
43 | 8B23C11F22CB7F49002C33D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
44 | 8B23C12122CB7F4B002C33D5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
45 | 8B23C12422CB7F4B002C33D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
46 | 8B23C12622CB7F4B002C33D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | 8B23C12C22CB9857002C33D5 /* LineCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineCell.swift; sourceTree = ""; };
48 | 8B23C12D22CB9857002C33D5 /* LineCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LineCell.xib; sourceTree = ""; };
49 | 8B23C13022CBA2A1002C33D5 /* LineDecorationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineDecorationView.swift; sourceTree = ""; };
50 | 8B23C13122CBA2A1002C33D5 /* LineDecorationView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LineDecorationView.xib; sourceTree = ""; };
51 | 8B23C13422CBAD50002C33D5 /* SectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionController.swift; sourceTree = ""; };
52 | 8B23C13822CBB52E002C33D5 /* SectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderView.swift; sourceTree = ""; };
53 | 8B23C13922CBB52E002C33D5 /* SectionHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SectionHeaderView.xib; sourceTree = ""; };
54 | /* End PBXFileReference section */
55 |
56 | /* Begin PBXFrameworksBuildPhase section */
57 | 8B23C11222CB7F49002C33D5 /* Frameworks */ = {
58 | isa = PBXFrameworksBuildPhase;
59 | buildActionMask = 2147483647;
60 | files = (
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXFrameworksBuildPhase section */
65 |
66 | /* Begin PBXGroup section */
67 | 8B184E6322CE22CC009F5EF7 /* Combines */ = {
68 | isa = PBXGroup;
69 | children = (
70 | 8B184E6422CE22EF009F5EF7 /* CombineSectionContainer.swift */,
71 | 8B184E7222CE34E4009F5EF7 /* Filter */,
72 | 8B184E6F22CE2C4F009F5EF7 /* Zip */,
73 | 8B184E6C22CE25A9009F5EF7 /* Merge */,
74 | 8B184E6922CE2331009F5EF7 /* Map */,
75 | 8B184E6622CE230C009F5EF7 /* CombineLatest */,
76 | );
77 | path = Combines;
78 | sourceTree = "";
79 | };
80 | 8B184E6622CE230C009F5EF7 /* CombineLatest */ = {
81 | isa = PBXGroup;
82 | children = (
83 | 8B184E6722CE2318009F5EF7 /* CombineLatestSectionContainer.swift */,
84 | );
85 | path = CombineLatest;
86 | sourceTree = "";
87 | };
88 | 8B184E6922CE2331009F5EF7 /* Map */ = {
89 | isa = PBXGroup;
90 | children = (
91 | 8B184E6A22CE234B009F5EF7 /* CombineMapSectionContainer.swift */,
92 | );
93 | path = Map;
94 | sourceTree = "";
95 | };
96 | 8B184E6C22CE25A9009F5EF7 /* Merge */ = {
97 | isa = PBXGroup;
98 | children = (
99 | 8B184E6D22CE25BD009F5EF7 /* CombineMergeSectionContainer.swift */,
100 | );
101 | path = Merge;
102 | sourceTree = "";
103 | };
104 | 8B184E6F22CE2C4F009F5EF7 /* Zip */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 8B184E7022CE2C89009F5EF7 /* CombineZipSectionContainer.swift */,
108 | );
109 | path = Zip;
110 | sourceTree = "";
111 | };
112 | 8B184E7222CE34E4009F5EF7 /* Filter */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 8B184E7322CE34F1009F5EF7 /* CombineFilterSectionContainer.swift */,
116 | );
117 | path = Filter;
118 | sourceTree = "";
119 | };
120 | 8B184E7622CE4F88009F5EF7 /* Model */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 8B23C13422CBAD50002C33D5 /* SectionController.swift */,
124 | );
125 | path = Model;
126 | sourceTree = "";
127 | };
128 | 8B184E7722CE4F97009F5EF7 /* Views */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 8B23C13022CBA2A1002C33D5 /* LineDecorationView.swift */,
132 | 8B23C13122CBA2A1002C33D5 /* LineDecorationView.xib */,
133 | 8B23C12C22CB9857002C33D5 /* LineCell.swift */,
134 | 8B23C12D22CB9857002C33D5 /* LineCell.xib */,
135 | 8B23C13822CBB52E002C33D5 /* SectionHeaderView.swift */,
136 | 8B23C13922CBB52E002C33D5 /* SectionHeaderView.xib */,
137 | );
138 | path = Views;
139 | sourceTree = "";
140 | };
141 | 8B184E7822CE4FBD009F5EF7 /* Resources */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 8B23C11E22CB7F49002C33D5 /* Main.storyboard */,
145 | 8B23C12122CB7F4B002C33D5 /* Assets.xcassets */,
146 | 8B23C12322CB7F4B002C33D5 /* LaunchScreen.storyboard */,
147 | );
148 | path = Resources;
149 | sourceTree = "";
150 | };
151 | 8B23C10C22CB7F49002C33D5 = {
152 | isa = PBXGroup;
153 | children = (
154 | 8B23C11722CB7F49002C33D5 /* CombineMarble */,
155 | 8B23C11622CB7F49002C33D5 /* Products */,
156 | );
157 | sourceTree = "";
158 | };
159 | 8B23C11622CB7F49002C33D5 /* Products */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 8B23C11522CB7F49002C33D5 /* Combine Visualizer.app */,
163 | );
164 | name = Products;
165 | sourceTree = "";
166 | };
167 | 8B23C11722CB7F49002C33D5 /* CombineMarble */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 8B184E7922CE50DD009F5EF7 /* CombineMarble.entitlements */,
171 | 8B23C11822CB7F49002C33D5 /* AppDelegate.swift */,
172 | 8B23C11A22CB7F49002C33D5 /* SceneDelegate.swift */,
173 | 8B23C11C22CB7F49002C33D5 /* ViewController.swift */,
174 | 8B23C12622CB7F4B002C33D5 /* Info.plist */,
175 | 8B184E7822CE4FBD009F5EF7 /* Resources */,
176 | 8B184E7722CE4F97009F5EF7 /* Views */,
177 | 8B184E7622CE4F88009F5EF7 /* Model */,
178 | 8B184E6322CE22CC009F5EF7 /* Combines */,
179 | );
180 | path = CombineMarble;
181 | sourceTree = "";
182 | };
183 | /* End PBXGroup section */
184 |
185 | /* Begin PBXNativeTarget section */
186 | 8B23C11422CB7F49002C33D5 /* CombineMarble */ = {
187 | isa = PBXNativeTarget;
188 | buildConfigurationList = 8B23C12922CB7F4B002C33D5 /* Build configuration list for PBXNativeTarget "CombineMarble" */;
189 | buildPhases = (
190 | 8B23C11122CB7F49002C33D5 /* Sources */,
191 | 8B23C11222CB7F49002C33D5 /* Frameworks */,
192 | 8B23C11322CB7F49002C33D5 /* Resources */,
193 | );
194 | buildRules = (
195 | );
196 | dependencies = (
197 | );
198 | name = CombineMarble;
199 | productName = CombineMarble;
200 | productReference = 8B23C11522CB7F49002C33D5 /* Combine Visualizer.app */;
201 | productType = "com.apple.product-type.application";
202 | };
203 | /* End PBXNativeTarget section */
204 |
205 | /* Begin PBXProject section */
206 | 8B23C10D22CB7F49002C33D5 /* Project object */ = {
207 | isa = PBXProject;
208 | attributes = {
209 | LastSwiftUpdateCheck = 1100;
210 | LastUpgradeCheck = 1100;
211 | ORGANIZATIONNAME = "Alfian Losari";
212 | TargetAttributes = {
213 | 8B23C11422CB7F49002C33D5 = {
214 | CreatedOnToolsVersion = 11.0;
215 | };
216 | };
217 | };
218 | buildConfigurationList = 8B23C11022CB7F49002C33D5 /* Build configuration list for PBXProject "CombineMarble" */;
219 | compatibilityVersion = "Xcode 9.3";
220 | developmentRegion = en;
221 | hasScannedForEncodings = 0;
222 | knownRegions = (
223 | en,
224 | Base,
225 | );
226 | mainGroup = 8B23C10C22CB7F49002C33D5;
227 | productRefGroup = 8B23C11622CB7F49002C33D5 /* Products */;
228 | projectDirPath = "";
229 | projectRoot = "";
230 | targets = (
231 | 8B23C11422CB7F49002C33D5 /* CombineMarble */,
232 | );
233 | };
234 | /* End PBXProject section */
235 |
236 | /* Begin PBXResourcesBuildPhase section */
237 | 8B23C11322CB7F49002C33D5 /* Resources */ = {
238 | isa = PBXResourcesBuildPhase;
239 | buildActionMask = 2147483647;
240 | files = (
241 | 8B23C13322CBA2A1002C33D5 /* LineDecorationView.xib in Resources */,
242 | 8B23C13B22CBB52E002C33D5 /* SectionHeaderView.xib in Resources */,
243 | 8B23C12522CB7F4B002C33D5 /* LaunchScreen.storyboard in Resources */,
244 | 8B23C12F22CB9857002C33D5 /* LineCell.xib in Resources */,
245 | 8B23C12222CB7F4B002C33D5 /* Assets.xcassets in Resources */,
246 | 8B23C12022CB7F49002C33D5 /* Main.storyboard in Resources */,
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | };
250 | /* End PBXResourcesBuildPhase section */
251 |
252 | /* Begin PBXSourcesBuildPhase section */
253 | 8B23C11122CB7F49002C33D5 /* Sources */ = {
254 | isa = PBXSourcesBuildPhase;
255 | buildActionMask = 2147483647;
256 | files = (
257 | 8B23C11D22CB7F49002C33D5 /* ViewController.swift in Sources */,
258 | 8B184E6E22CE25BD009F5EF7 /* CombineMergeSectionContainer.swift in Sources */,
259 | 8B23C12E22CB9857002C33D5 /* LineCell.swift in Sources */,
260 | 8B23C11922CB7F49002C33D5 /* AppDelegate.swift in Sources */,
261 | 8B184E6822CE2318009F5EF7 /* CombineLatestSectionContainer.swift in Sources */,
262 | 8B184E6B22CE234B009F5EF7 /* CombineMapSectionContainer.swift in Sources */,
263 | 8B184E7122CE2C89009F5EF7 /* CombineZipSectionContainer.swift in Sources */,
264 | 8B23C13222CBA2A1002C33D5 /* LineDecorationView.swift in Sources */,
265 | 8B184E7422CE34F1009F5EF7 /* CombineFilterSectionContainer.swift in Sources */,
266 | 8B23C13A22CBB52E002C33D5 /* SectionHeaderView.swift in Sources */,
267 | 8B184E6522CE22EF009F5EF7 /* CombineSectionContainer.swift in Sources */,
268 | 8B23C11B22CB7F49002C33D5 /* SceneDelegate.swift in Sources */,
269 | 8B23C13522CBAD50002C33D5 /* SectionController.swift in Sources */,
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | };
273 | /* End PBXSourcesBuildPhase section */
274 |
275 | /* Begin PBXVariantGroup section */
276 | 8B23C11E22CB7F49002C33D5 /* Main.storyboard */ = {
277 | isa = PBXVariantGroup;
278 | children = (
279 | 8B23C11F22CB7F49002C33D5 /* Base */,
280 | );
281 | name = Main.storyboard;
282 | sourceTree = "";
283 | };
284 | 8B23C12322CB7F4B002C33D5 /* LaunchScreen.storyboard */ = {
285 | isa = PBXVariantGroup;
286 | children = (
287 | 8B23C12422CB7F4B002C33D5 /* Base */,
288 | );
289 | name = LaunchScreen.storyboard;
290 | sourceTree = "";
291 | };
292 | /* End PBXVariantGroup section */
293 |
294 | /* Begin XCBuildConfiguration section */
295 | 8B23C12722CB7F4B002C33D5 /* Debug */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ALWAYS_SEARCH_USER_PATHS = NO;
299 | CLANG_ANALYZER_NONNULL = YES;
300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
302 | CLANG_CXX_LIBRARY = "libc++";
303 | CLANG_ENABLE_MODULES = YES;
304 | CLANG_ENABLE_OBJC_ARC = YES;
305 | CLANG_ENABLE_OBJC_WEAK = YES;
306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
307 | CLANG_WARN_BOOL_CONVERSION = YES;
308 | CLANG_WARN_COMMA = YES;
309 | CLANG_WARN_CONSTANT_CONVERSION = YES;
310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
313 | CLANG_WARN_EMPTY_BODY = YES;
314 | CLANG_WARN_ENUM_CONVERSION = YES;
315 | CLANG_WARN_INFINITE_RECURSION = YES;
316 | CLANG_WARN_INT_CONVERSION = YES;
317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
321 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
322 | CLANG_WARN_STRICT_PROTOTYPES = YES;
323 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
325 | CLANG_WARN_UNREACHABLE_CODE = YES;
326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
327 | COPY_PHASE_STRIP = NO;
328 | DEBUG_INFORMATION_FORMAT = dwarf;
329 | ENABLE_STRICT_OBJC_MSGSEND = YES;
330 | ENABLE_TESTABILITY = YES;
331 | GCC_C_LANGUAGE_STANDARD = gnu11;
332 | GCC_DYNAMIC_NO_PIC = NO;
333 | GCC_NO_COMMON_BLOCKS = YES;
334 | GCC_OPTIMIZATION_LEVEL = 0;
335 | GCC_PREPROCESSOR_DEFINITIONS = (
336 | "DEBUG=1",
337 | "$(inherited)",
338 | );
339 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
340 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
341 | GCC_WARN_UNDECLARED_SELECTOR = YES;
342 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
343 | GCC_WARN_UNUSED_FUNCTION = YES;
344 | GCC_WARN_UNUSED_VARIABLE = YES;
345 | INFOPLIST_FILE = "";
346 | "INFOPLIST_FILE[sdk=*]" = "";
347 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
348 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
349 | MTL_FAST_MATH = YES;
350 | ONLY_ACTIVE_ARCH = YES;
351 | SDKROOT = iphoneos;
352 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
353 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
354 | };
355 | name = Debug;
356 | };
357 | 8B23C12822CB7F4B002C33D5 /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ALWAYS_SEARCH_USER_PATHS = NO;
361 | CLANG_ANALYZER_NONNULL = YES;
362 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
363 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
364 | CLANG_CXX_LIBRARY = "libc++";
365 | CLANG_ENABLE_MODULES = YES;
366 | CLANG_ENABLE_OBJC_ARC = YES;
367 | CLANG_ENABLE_OBJC_WEAK = YES;
368 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
369 | CLANG_WARN_BOOL_CONVERSION = YES;
370 | CLANG_WARN_COMMA = YES;
371 | CLANG_WARN_CONSTANT_CONVERSION = YES;
372 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
373 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
374 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
375 | CLANG_WARN_EMPTY_BODY = YES;
376 | CLANG_WARN_ENUM_CONVERSION = YES;
377 | CLANG_WARN_INFINITE_RECURSION = YES;
378 | CLANG_WARN_INT_CONVERSION = YES;
379 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
380 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
381 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
384 | CLANG_WARN_STRICT_PROTOTYPES = YES;
385 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
386 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
387 | CLANG_WARN_UNREACHABLE_CODE = YES;
388 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
389 | COPY_PHASE_STRIP = NO;
390 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
391 | ENABLE_NS_ASSERTIONS = NO;
392 | ENABLE_STRICT_OBJC_MSGSEND = YES;
393 | GCC_C_LANGUAGE_STANDARD = gnu11;
394 | GCC_NO_COMMON_BLOCKS = YES;
395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
397 | GCC_WARN_UNDECLARED_SELECTOR = YES;
398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
399 | GCC_WARN_UNUSED_FUNCTION = YES;
400 | GCC_WARN_UNUSED_VARIABLE = YES;
401 | INFOPLIST_FILE = "";
402 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
403 | MTL_ENABLE_DEBUG_INFO = NO;
404 | MTL_FAST_MATH = YES;
405 | SDKROOT = iphoneos;
406 | SWIFT_COMPILATION_MODE = wholemodule;
407 | SWIFT_OPTIMIZATION_LEVEL = "-O";
408 | VALIDATE_PRODUCT = YES;
409 | };
410 | name = Release;
411 | };
412 | 8B23C12A22CB7F4B002C33D5 /* Debug */ = {
413 | isa = XCBuildConfiguration;
414 | buildSettings = {
415 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
416 | CODE_SIGN_ENTITLEMENTS = CombineMarble/CombineMarble.entitlements;
417 | CODE_SIGN_STYLE = Automatic;
418 | DERIVE_UIKITFORMAC_PRODUCT_BUNDLE_IDENTIFIER = YES;
419 | DEVELOPMENT_TEAM = 5C2XD9H2JS;
420 | INFOPLIST_FILE = CombineMarble/Info.plist;
421 | LD_RUNPATH_SEARCH_PATHS = (
422 | "$(inherited)",
423 | "@executable_path/Frameworks",
424 | );
425 | PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.CombineMarble;
426 | PRODUCT_NAME = " Combine Visualizer";
427 | SUPPORTS_UIKITFORMAC = YES;
428 | SWIFT_VERSION = 5.0;
429 | TARGETED_DEVICE_FAMILY = "1,2";
430 | };
431 | name = Debug;
432 | };
433 | 8B23C12B22CB7F4B002C33D5 /* Release */ = {
434 | isa = XCBuildConfiguration;
435 | buildSettings = {
436 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
437 | CODE_SIGN_ENTITLEMENTS = CombineMarble/CombineMarble.entitlements;
438 | CODE_SIGN_STYLE = Automatic;
439 | DERIVE_UIKITFORMAC_PRODUCT_BUNDLE_IDENTIFIER = YES;
440 | DEVELOPMENT_TEAM = 5C2XD9H2JS;
441 | INFOPLIST_FILE = CombineMarble/Info.plist;
442 | LD_RUNPATH_SEARCH_PATHS = (
443 | "$(inherited)",
444 | "@executable_path/Frameworks",
445 | );
446 | PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.CombineMarble;
447 | PRODUCT_NAME = " Combine Visualizer";
448 | SUPPORTS_UIKITFORMAC = YES;
449 | SWIFT_VERSION = 5.0;
450 | TARGETED_DEVICE_FAMILY = "1,2";
451 | };
452 | name = Release;
453 | };
454 | /* End XCBuildConfiguration section */
455 |
456 | /* Begin XCConfigurationList section */
457 | 8B23C11022CB7F49002C33D5 /* Build configuration list for PBXProject "CombineMarble" */ = {
458 | isa = XCConfigurationList;
459 | buildConfigurations = (
460 | 8B23C12722CB7F4B002C33D5 /* Debug */,
461 | 8B23C12822CB7F4B002C33D5 /* Release */,
462 | );
463 | defaultConfigurationIsVisible = 0;
464 | defaultConfigurationName = Release;
465 | };
466 | 8B23C12922CB7F4B002C33D5 /* Build configuration list for PBXNativeTarget "CombineMarble" */ = {
467 | isa = XCConfigurationList;
468 | buildConfigurations = (
469 | 8B23C12A22CB7F4B002C33D5 /* Debug */,
470 | 8B23C12B22CB7F4B002C33D5 /* Release */,
471 | );
472 | defaultConfigurationIsVisible = 0;
473 | defaultConfigurationName = Release;
474 | };
475 | /* End XCConfigurationList section */
476 | };
477 | rootObject = 8B23C10D22CB7F49002C33D5 /* Project object */;
478 | }
479 |
--------------------------------------------------------------------------------