├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── SwiftUI-BLE-Project
├── Resouce
│ └── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── View
│ ├── ContentView.swift
│ ├── DetailView.swift
│ └── ListView.swift
├── ViewModel
│ ├── Navigation
│ │ └── SwiftUI_BLE_ProjectApp.swift
│ └── CoreBluetooth
│ │ ├── CoreBluetoothViewModelExtension+SwiftUIView.swift.swift
│ │ ├── CoreBluetoothViewModelExtension+Delegate.swift
│ │ └── CoreBluetoothViewModel.swift
├── Model
│ └── CoreBluetooth
│ │ ├── Mock
│ │ ├── Mock.swift
│ │ ├── ServiceCharacteristicsMock.swift
│ │ ├── CBCentralManagerMock.swift
│ │ └── CBPeripheralMock.swift
│ │ ├── Store
│ │ ├── Service.swift
│ │ ├── Peripheral.swift
│ │ └── Characteristic.swift
│ │ └── Delegate
│ │ └── CBPeripheralProtcolDelegate.swift
└── Info.plist
├── SwiftUI-BLE-Project.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── kazuyaito.xcuserdatad
│ │ ├── xcschemes
│ │ └── xcschememanagement.plist
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
└── project.pbxproj
├── README.md
├── LICENSE
└── .gitignore
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Resouce/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Resouce/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Project
2 | * SwiftUI × CoreBluetooth Sample Code ...
3 | # Built With
4 | * CoreBluetooth
5 | # Versioning
6 | * target -> iOS 14.1 ↑
7 | * Xcode --12.4
8 | * Swift -- 5.3
9 | * SwiftUI -- 2.0
10 | # Authors
11 | * kazuya ito
12 |
13 |
14 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/View/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ContentView: View {
11 | var body: some View {
12 | NavigationView {
13 | ListView()
14 | }
15 | .navigationViewStyle(StackNavigationViewStyle())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## チケットへのリンク
2 |
3 | * https://example.com
4 |
5 | ## やったこと
6 |
7 | * このプルリクで何をしたのか?
8 |
9 | ## やらないこと
10 |
11 | * このプルリクでやらないことは何か?(あれば。無いなら「無し」でOK)
12 |
13 | ## できるようになること(ユーザ目線)
14 |
15 | * 何ができるようになるのか?(あれば。無いなら「無し」でOK)
16 |
17 | ## できなくなること(ユーザ目線)
18 |
19 | * 何ができなくなるのか?(あれば。無いなら「無し」でOK)
20 |
21 | ## 動作確認
22 |
23 | * どのような動作確認を行ったのか? 結果はどうか?
24 |
25 | ## その他
26 |
27 | * レビュワーへの参考情報(実装上の懸念点や注意点などあれば記載)
28 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/ViewModel/Navigation/SwiftUI_BLE_ProjectApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftUI_BLE_ProjectApp.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct SwiftUI_BLE_ProjectApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | .environmentObject(CoreBluetoothViewModel())
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Mock/Mock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mock.swift
3 | // factory-tourguide-iOS
4 | //
5 | // Created by kazuya ito on 2020/10/28.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol Mock {}
11 |
12 | extension Mock {
13 | var className: String {
14 | return String(describing: type(of: self))
15 | }
16 |
17 | func log(_ message: String? = nil) {
18 | print("Mocked -", className, message ?? "")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project.xcodeproj/xcuserdata/kazuyaito.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftUI-BLE-Project.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Store/Service.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Service.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/03.
6 | //
7 |
8 | import CoreBluetooth
9 |
10 | class Service: Identifiable {
11 | var id: UUID
12 | var uuid: CBUUID
13 | var service: CBService
14 |
15 | init(_uuid: CBUUID,
16 | _service: CBService) {
17 |
18 | id = UUID()
19 | uuid = _uuid
20 | service = _service
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Store/Peripheral.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Peripheral.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import CoreBluetooth
9 |
10 | class Peripheral: Identifiable {
11 | var id: UUID
12 | var peripheral: CBPeripheralProtocol
13 | var name: String
14 | var advertisementData: [String : Any]
15 | var rssi: Int
16 | var discoverCount: Int
17 |
18 | init(_peripheral: CBPeripheralProtocol,
19 | _name: String,
20 | _advData: [String : Any],
21 | _rssi: NSNumber,
22 | _discoverCount: Int) {
23 | id = UUID()
24 | peripheral = _peripheral
25 | name = _name
26 | advertisementData = _advData
27 | rssi = _rssi.intValue
28 | discoverCount = _discoverCount + 1
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Store/Characteristic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Characteristic.swift
3 | // factory-tourguide-iOS
4 | //
5 | // Created by kazuya ito on 2020/10/29.
6 | //
7 |
8 | import CoreBluetooth
9 |
10 | class Characteristic: Identifiable {
11 | var id: UUID
12 | var characteristic: CBCharacteristic
13 | var description: String
14 | var uuid: CBUUID
15 | var readValue: String
16 | var service: CBService
17 |
18 | init(_characteristic: CBCharacteristic,
19 | _description: String,
20 | _uuid: CBUUID,
21 | _readValue: String,
22 | _service: CBService) {
23 |
24 | id = UUID()
25 | characteristic = _characteristic
26 | description = _description == "" ? "NoName" : _description
27 | uuid = _uuid
28 | readValue = _readValue == "" ? "NoData" : _readValue
29 | service = _service
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 braveridge
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/ViewModel/CoreBluetooth/CoreBluetoothViewModelExtension+SwiftUIView.swift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CoreBluetoothViewModelExtension+SwiftUIView.swift.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/08/24.
6 | //
7 |
8 | import SwiftUI
9 | import CoreBluetooth
10 |
11 | //MARK: - Navigation Items
12 | extension CoreBluetoothViewModel {
13 | func navigationToDetailView(isDetailViewLinkActive: Binding) -> some View {
14 | let navigationToDetailView =
15 | NavigationLink("",
16 | destination: DetailView(),
17 | isActive: isDetailViewLinkActive).frame(width: 0, height: 0)
18 | return navigationToDetailView
19 | }
20 | }
21 |
22 | //MARK: - View Items
23 | extension CoreBluetoothViewModel {
24 | func UIButtonView(proxy: GeometryProxy, text: String) -> some View {
25 | let UIButtonView =
26 | VStack {
27 | Text(text)
28 | .frame(width: proxy.size.width / 1.1,
29 | height: 50,
30 | alignment: .center)
31 | .foregroundColor(Color.blue)
32 | .overlay(
33 | RoundedRectangle(cornerRadius: 10)
34 | .stroke(Color.blue, lineWidth: 2))
35 | }
36 | return UIButtonView
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Mock/ServiceCharacteristicsMock.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import CoreBluetooth
3 |
4 | class ServiceCharacteristicsMock {
5 | private var value: Data = Data([UInt8(0x00)])
6 |
7 | private let serviceUuid: CBUUID = CBUUID(string: "00112233-4455-6677-8899-AABBCCDDEEFF")
8 | private let characteristicUuid: CBUUID = CBUUID(string: "10112233-4455-6677-8899-AABBCCDDEEFF")
9 |
10 | public func service() -> [CBMutableService] {
11 | return [
12 | CBMutableService(type: serviceUuid, primary: true),
13 | ]
14 | }
15 |
16 | public func characteristics(_ serviceUUID: CBUUID) -> [CBCharacteristic] {
17 | switch serviceUUID {
18 | case serviceUuid:
19 | return [
20 | mutableCharacteristic(uuid: characteristicUuid),
21 | ]
22 | default:
23 | return []
24 | }
25 | }
26 |
27 | private func mutableCharacteristic(uuid: CBUUID) -> CBMutableCharacteristic {
28 | return CBMutableCharacteristic(type: uuid,
29 | properties: [.read, .write, .notify],
30 | value: nil,
31 | permissions: .readable)
32 | }
33 |
34 | public func value(uuid: CBUUID) -> Data {
35 | switch uuid {
36 | case characteristicUuid:
37 | return value
38 |
39 | default:
40 | return Data()
41 | }
42 | }
43 |
44 | public func writeValue(uuid: CBUUID, writeValue: Data) {
45 | switch uuid {
46 | case characteristicUuid:
47 | value = writeValue
48 |
49 | default:
50 | break
51 | }
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Resouce/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/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 | $(CURRENT_PROJECT_VERSION)
21 | LSRequiresIPhoneOS
22 |
23 | NSBluetoothAlwaysUsageDescription
24 | Bluetoothでデバイスと接続する為に使用します。
25 | NSBluetoothPeripheralUsageDescription
26 | Bluetoothでデバイスと接続する為に使用します。
27 | UIApplicationSceneManifest
28 |
29 | UIApplicationSupportsMultipleScenes
30 |
31 |
32 | UIApplicationSupportsIndirectInputEvents
33 |
34 | UILaunchScreen
35 |
36 | UIRequiredDeviceCapabilities
37 |
38 | armv7
39 |
40 | UISupportedInterfaceOrientations
41 |
42 | UIInterfaceOrientationPortrait
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 | UIInterfaceOrientationPortraitUpsideDown
46 |
47 | UISupportedInterfaceOrientations~ipad
48 |
49 | UIInterfaceOrientationPortrait
50 | UIInterfaceOrientationPortraitUpsideDown
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/swift
2 | # Edit at https://www.gitignore.io/?templates=swift
3 |
4 | ### Swift ###
5 | # Xcode
6 | #
7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
8 |
9 | ## Build generated
10 | build/
11 | DerivedData/
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata/
23 |
24 | ## Other
25 | *.moved-aside
26 | *.xccheckout
27 | *.xcscmblueprint
28 |
29 | ## Obj-C/Swift specific
30 | *.hmap
31 | *.ipa
32 | *.dSYM.zip
33 | *.dSYM
34 |
35 | ## Playgrounds
36 | timeline.xctimeline
37 | playground.xcworkspace
38 |
39 | # Swift Package Manager
40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
41 | # Packages/
42 | # Package.pins
43 | # Package.resolved
44 | .build/
45 |
46 | # CocoaPods
47 | # We recommend against adding the Pods directory to your .gitignore. However
48 | # you should judge for yourself, the pros and cons are mentioned at:
49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
50 | Pods/
51 | # Add this line if you want to avoid checking in source code from the Xcode workspace
52 | # *.xcworkspace
53 |
54 | # Carthage
55 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
56 | # Carthage/Checkouts
57 |
58 | Carthage/Build
59 |
60 | # fastlane
61 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
62 | # screenshots whenever they are needed.
63 | # For more information about the recommended setup visit:
64 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
65 |
66 | fastlane/report.xml
67 | fastlane/Preview.html
68 | fastlane/screenshots/**/*.png
69 | fastlane/test_output
70 |
71 | # Code Injection
72 | # After new code Injection tools there's a generated folder /iOSInjectionProject
73 | # https://github.com/johnno1962/injectionforxcode
74 |
75 | iOSInjectionProject/
76 |
77 | # End of https://www.gitignore.io/api/swift
78 |
79 | .DS_Store
80 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/ViewModel/CoreBluetooth/CoreBluetoothViewModelExtension+Delegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CoreBluetoothViewModelExtension.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import CoreBluetooth
9 |
10 | //MARK: ViewModelSetup
11 | extension CoreBluetoothViewModel: CBCentralManagerDelegate, CBPeripheralDelegate {
12 |
13 | func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
14 | didDiscoverServices(peripheral, error: error)
15 | }
16 |
17 | func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
18 | didDiscoverCharacteristics(peripheral, service: service, error: error)
19 | }
20 |
21 | func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
22 | didUpdateValue(peripheral, characteristic: characteristic, error: error)
23 | }
24 |
25 | func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
26 | didWriteValue(peripheral, descriptor: descriptor, error: error)
27 | }
28 |
29 | func centralManagerDidUpdateState(_ central: CBCentralManager) {
30 | didUpdateState(central)
31 | }
32 |
33 | func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
34 | willRestoreState(central, dict: dict)
35 | }
36 |
37 | func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
38 | didDiscover(central, peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
39 | }
40 |
41 | func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
42 | didConnect(central, peripheral: peripheral)
43 | }
44 |
45 | func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
46 | didFailToConnect(central, peripheral: peripheral, error: error)
47 | }
48 |
49 | func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
50 | didDisconnect(central, peripheral: peripheral, error: error)
51 | }
52 |
53 | func centralManager(_ central: CBCentralManager,
54 | connectionEventDidOccur event: CBConnectionEvent,
55 | for peripheral: CBPeripheral) {
56 | connectionEventDidOccur(central, event: event, peripheral: peripheral)
57 | }
58 |
59 | func centralManager(_ central: CBCentralManager, didUpdateANCSAuthorizationFor peripheral: CBPeripheral) {
60 | didUpdateANCSAuthorization(central, peripheral: peripheral)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Mock/CBCentralManagerMock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CBCentralManagerMock.swift
3 | // factory-tourguide-iOS
4 | //
5 | // Created by kazuya ito on 2020/10/28.
6 | //
7 |
8 | import Foundation
9 | import CoreBluetooth
10 |
11 | public class CBCentralManagerMock : Mock, CBCentralManagerProtocol {
12 | public var delegate: CBCentralManagerDelegate?
13 | public var state: CBManagerState = .poweredOff
14 | public var isScanning: Bool = false
15 | public var deviceLocalName: String = "ble device"
16 |
17 | required public init(delegate: CBCentralManagerDelegate?, queue: DispatchQueue?, options: [String : Any]? = nil) {
18 | log(#function)
19 |
20 | self.delegate = delegate
21 |
22 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
23 | self.state = .poweredOn
24 |
25 | if let delegate = self.delegate as? CBCentralManagerProtocolDelegate {
26 | delegate.didUpdateState(self)
27 | }
28 | }
29 |
30 | }
31 |
32 | public func scanForPeripherals(withServices serviceUUIDs: [CBUUID]?, options: [String : Any]? = nil) {
33 | log(#function)
34 | isScanning = true
35 |
36 | if let delegate = delegate as? CoreBluetoothViewModel {
37 | let discoveredPeripheral = CBPeripheralMock(identifier: UUID(),
38 | name: deviceLocalName,
39 | manager: self)
40 | //dummy peripheral
41 | delegate.didDiscover(self,
42 | peripheral: discoveredPeripheral,
43 | advertisementData: [:],
44 | rssi: -30)
45 | }
46 | }
47 |
48 | public func stopScan() {
49 | log(#function)
50 | isScanning = false
51 | }
52 |
53 | public func connect(_ peripheral: CBPeripheralProtocol, options: [String : Any]? = nil) {
54 | log(#function)
55 |
56 | if let delegate = delegate as? CBCentralManagerProtocolDelegate {
57 | delegate.didConnect(self,
58 | peripheral: peripheral)
59 | }
60 | }
61 |
62 | public func cancelPeripheralConnection(_ peripheral: CBPeripheralProtocol) {
63 | log(#function)
64 |
65 | if let delegate = delegate as? CBCentralManagerProtocolDelegate {
66 |
67 | delegate.didDisconnect(self,
68 | peripheral: peripheral,
69 | error: nil)
70 |
71 | }
72 | }
73 |
74 | public func retrievePeripherals(_ identifiers: [UUID]) -> [CBPeripheralProtocol] {
75 | log(#function)
76 |
77 | return identifiers.map { CBPeripheralMock(identifier: $0,
78 | name: deviceLocalName,
79 | manager: self) }
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/View/DetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailView.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct DetailView: View {
11 | @EnvironmentObject var bleManager: CoreBluetoothViewModel
12 |
13 | var body: some View {
14 | GeometryReader { proxy in
15 | VStack {
16 | Button(action: {
17 | bleManager.disconnectPeripheral()
18 | bleManager.stopScan()
19 | }) {
20 | bleManager.UIButtonView(proxy: proxy, text: "切断する")
21 | }
22 |
23 | Text(bleManager.isBlePower ? "" : "Bluetooth設定がOFFです")
24 | .padding(10)
25 |
26 | List {
27 | CharacteriticCells()
28 | }
29 | .navigationBarTitle("コネクト結果")
30 | .navigationBarBackButtonHidden(true)
31 | }
32 | }
33 | }
34 |
35 | struct CharacteriticCells: View {
36 | @EnvironmentObject var bleManager: CoreBluetoothViewModel
37 |
38 | var body: some View {
39 | ForEach(0.. [CBPeripheralProtocol]
75 | }
76 |
77 | extension CBCentralManager : CBCentralManagerProtocol {
78 | public func connect(_ peripheral: CBPeripheralProtocol, options: [String: Any]?) {
79 | guard let peripheral = peripheral as? CBPeripheral else { return }
80 | connect(peripheral, options: options)
81 | }
82 |
83 | public func cancelPeripheralConnection(_ peripheral: CBPeripheralProtocol) {
84 | guard let peripheral = peripheral as? CBPeripheral else { return }
85 | cancelPeripheralConnection(peripheral)
86 | }
87 |
88 | public func retrievePeripherals(_ identifiers: [UUID]) -> [CBPeripheralProtocol] {
89 | return retrievePeripherals(withIdentifiers: identifiers)
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/Model/CoreBluetooth/Mock/CBPeripheralMock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CBPeripheralMock.swift
3 | // factory-tourguide-iOS
4 | //
5 | // Created by kazuya ito on 2020/10/28.
6 | //
7 |
8 | import Foundation
9 | import CoreBluetooth
10 |
11 | class CBPeripheralMock: Mock, CBPeripheralProtocol {
12 | weak var delegate: CBPeripheralDelegate?
13 | var state: CBPeripheralState = .disconnected
14 | var identifier: UUID
15 | var name: String?
16 | var services: [CBService]?
17 | var manager: CBCentralManagerMock
18 |
19 | private var serviceCharacteristic = ServiceCharacteristicsMock()
20 |
21 | var debugDescription: String {
22 | return "\(identifier) \(name ?? "")"
23 | }
24 |
25 | init(identifier: UUID, name: String?, manager: CBCentralManagerMock) {
26 | self.identifier = identifier
27 | self.name = name
28 | self.manager = manager
29 | log(#function)
30 | }
31 |
32 | func didConnect(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol){
33 | state = .connected
34 | }
35 |
36 | func didDisconnect(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol, error: Error?) {
37 | state = .disconnected
38 | }
39 |
40 | func discoverServices(_ serviceUUIDs: [CBUUID]?) {
41 | log(#function)
42 |
43 | services = serviceCharacteristic.service()
44 |
45 | guard let delegate = delegate as? CBPeripheralProtocolDelegate else { return }
46 | delegate.didDiscoverServices(self, error: nil)
47 | }
48 |
49 | func discoverCharacteristics(_ characteristicUUIDs: [CBUUID]?, for service: CBService) {
50 | log(#function)
51 | guard let mutableService = service as? CBMutableService,
52 | let delegate = delegate as? CBPeripheralProtocolDelegate
53 | else { return }
54 |
55 | mutableService.characteristics = serviceCharacteristic.characteristics(service.uuid)
56 |
57 | delegate.didDiscoverCharacteristics(self, service: mutableService, error: nil)
58 | }
59 |
60 | func readValue(for characteristic: CBCharacteristic) {
61 | log(#function)
62 |
63 | guard let mutableCharacteristic = characteristic as? CBMutableCharacteristic,
64 | let delegate = delegate as? CBPeripheralProtocolDelegate
65 | else { return }
66 |
67 | mutableCharacteristic.value = serviceCharacteristic.value(uuid: mutableCharacteristic.uuid)
68 |
69 | if let _ = mutableCharacteristic.value {
70 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
71 | delegate.didUpdateValue(self,
72 | characteristic: characteristic,
73 | error: nil)
74 | }
75 | }
76 | }
77 |
78 | func writeValue(_ data: Data, for characteristic: CBCharacteristic, type: CBCharacteristicWriteType) {
79 | log(#function)
80 |
81 | guard let mutableCharacteristic = characteristic as? CBMutableCharacteristic,
82 | let delegate = delegate as? CBPeripheralProtocolDelegate
83 | else { return }
84 |
85 | serviceCharacteristic.writeValue(uuid: mutableCharacteristic.uuid, writeValue: data)
86 |
87 | mutableCharacteristic.value = serviceCharacteristic.value(uuid: mutableCharacteristic.uuid)
88 |
89 | if let _ = mutableCharacteristic.value {
90 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
91 | delegate.didUpdateValue(self,
92 | characteristic: characteristic,
93 | error: nil)
94 | }
95 | }
96 | }
97 |
98 | func setNotifyValue(_ enabled: Bool, for characteristic: CBCharacteristic) {
99 | log(#function)
100 | }
101 |
102 | private func dataNotify(_ delegate: CBPeripheralProtocolDelegate) {
103 | log(#function)
104 | }
105 |
106 | func discoverDescriptors(for characteristic: CBCharacteristic) {
107 | log(#function)
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project/ViewModel/CoreBluetooth/CoreBluetoothViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CoreBluetoothViewModel.swift
3 | // SwiftUI-BLE-Project
4 | //
5 | // Created by kazuya ito on 2021/02/02.
6 | //
7 |
8 | import SwiftUI
9 | import CoreBluetooth
10 |
11 | class CoreBluetoothViewModel: NSObject, ObservableObject, CBPeripheralProtocolDelegate, CBCentralManagerProtocolDelegate {
12 |
13 | @Published var isBlePower: Bool = false
14 | @Published var isSearching: Bool = false
15 | @Published var isConnected: Bool = false
16 |
17 | @Published var foundPeripherals: [Peripheral] = []
18 | @Published var foundServices: [Service] = []
19 | @Published var foundCharacteristics: [Characteristic] = []
20 |
21 | private var centralManager: CBCentralManagerProtocol!
22 | private var connectedPeripheral: Peripheral!
23 |
24 | private let serviceUUID: CBUUID = CBUUID()
25 |
26 | override init() {
27 | super.init()
28 | #if targetEnvironment(simulator)
29 | centralManager = CBCentralManagerMock(delegate: self, queue: nil)
30 | #else
31 | centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true])
32 | #endif
33 | }
34 |
35 | private func resetConfigure() {
36 | withAnimation {
37 | isSearching = false
38 | isConnected = false
39 |
40 | foundPeripherals = []
41 | foundServices = []
42 | foundCharacteristics = []
43 | }
44 | }
45 |
46 | //Control Func
47 | func startScan() {
48 | let scanOption = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
49 | centralManager?.scanForPeripherals(withServices: nil, options: scanOption)
50 | print("# Start Scan")
51 | isSearching = true
52 | }
53 |
54 | func stopScan(){
55 | disconnectPeripheral()
56 | centralManager?.stopScan()
57 | print("# Stop Scan")
58 | isSearching = false
59 | }
60 |
61 | func connectPeripheral(_ selectPeripheral: Peripheral?) {
62 | guard let connectPeripheral = selectPeripheral else { return }
63 | connectedPeripheral = selectPeripheral
64 | centralManager.connect(connectPeripheral.peripheral, options: nil)
65 | }
66 |
67 | func disconnectPeripheral() {
68 | guard let connectedPeripheral = connectedPeripheral else { return }
69 | centralManager.cancelPeripheralConnection(connectedPeripheral.peripheral)
70 | }
71 |
72 | //MARK: CoreBluetooth CentralManager Delegete Func
73 | func didUpdateState(_ central: CBCentralManagerProtocol) {
74 | if central.state == .poweredOn {
75 | isBlePower = true
76 | } else {
77 | isBlePower = false
78 | }
79 | }
80 |
81 | func didDiscover(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol, advertisementData: [String : Any], rssi: NSNumber) {
82 | if rssi.intValue >= 0 { return }
83 |
84 | let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String ?? nil
85 | var _name = "NoName"
86 |
87 | if peripheralName != nil {
88 | _name = String(peripheralName!)
89 | } else if peripheral.name != nil {
90 | _name = String(peripheral.name!)
91 | }
92 |
93 | let foundPeripheral: Peripheral = Peripheral(_peripheral: peripheral,
94 | _name: _name,
95 | _advData: advertisementData,
96 | _rssi: rssi,
97 | _discoverCount: 0)
98 |
99 | if let index = foundPeripherals.firstIndex(where: { $0.peripheral.identifier.uuidString == peripheral.identifier.uuidString }) {
100 | if foundPeripherals[index].discoverCount % 50 == 0 {
101 | foundPeripherals[index].name = _name
102 | foundPeripherals[index].rssi = rssi.intValue
103 | foundPeripherals[index].discoverCount += 1
104 | } else {
105 | foundPeripherals[index].discoverCount += 1
106 | }
107 | } else {
108 | foundPeripherals.append(foundPeripheral)
109 | DispatchQueue.main.async { self.isSearching = false }
110 | }
111 | }
112 |
113 | func didConnect(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol) {
114 | guard let connectedPeripheral = connectedPeripheral else { return }
115 | isConnected = true
116 | connectedPeripheral.peripheral.delegate = self
117 | connectedPeripheral.peripheral.discoverServices(nil)
118 | }
119 |
120 | func didFailToConnect(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol, error: Error?) {
121 | disconnectPeripheral()
122 | }
123 |
124 | func didDisconnect(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol, error: Error?) {
125 | print("disconnect")
126 | resetConfigure()
127 | }
128 |
129 | func connectionEventDidOccur(_ central: CBCentralManagerProtocol, event: CBConnectionEvent, peripheral: CBPeripheralProtocol) {
130 |
131 | }
132 |
133 | func willRestoreState(_ central: CBCentralManagerProtocol, dict: [String : Any]) {
134 |
135 | }
136 |
137 | func didUpdateANCSAuthorization(_ central: CBCentralManagerProtocol, peripheral: CBPeripheralProtocol) {
138 |
139 | }
140 |
141 | //MARK: CoreBluetooth Peripheral Delegate Func
142 | func didDiscoverServices(_ peripheral: CBPeripheralProtocol, error: Error?) {
143 | peripheral.services?.forEach { service in
144 | let setService = Service(_uuid: service.uuid, _service: service)
145 |
146 | foundServices.append(setService)
147 | peripheral.discoverCharacteristics(nil, for: service)
148 | }
149 | }
150 |
151 | func didDiscoverCharacteristics(_ peripheral: CBPeripheralProtocol, service: CBService, error: Error?) {
152 | service.characteristics?.forEach { characteristic in
153 | let setCharacteristic: Characteristic = Characteristic(_characteristic: characteristic,
154 | _description: "",
155 | _uuid: characteristic.uuid,
156 | _readValue: "",
157 | _service: characteristic.service)
158 | foundCharacteristics.append(setCharacteristic)
159 | peripheral.readValue(for: characteristic)
160 | }
161 | }
162 |
163 | func didUpdateValue(_ peripheral: CBPeripheralProtocol, characteristic: CBCharacteristic, error: Error?) {
164 | guard let characteristicValue = characteristic.value else { return }
165 |
166 | if let index = foundCharacteristics.firstIndex(where: { $0.uuid.uuidString == characteristic.uuid.uuidString }) {
167 |
168 | foundCharacteristics[index].readValue = characteristicValue.map({ String(format:"%02x", $0) }).joined()
169 | }
170 | }
171 |
172 | func didWriteValue(_ peripheral: CBPeripheralProtocol, descriptor: CBDescriptor, error: Error?) {
173 |
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project.xcodeproj/xcuserdata/kazuyaito.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
21 |
22 |
23 |
25 |
37 |
38 |
39 |
41 |
53 |
54 |
55 |
57 |
69 |
70 |
71 |
73 |
85 |
86 |
87 |
89 |
101 |
102 |
103 |
105 |
117 |
118 |
119 |
121 |
133 |
134 |
135 |
137 |
149 |
150 |
164 |
165 |
179 |
180 |
194 |
195 |
196 |
197 |
198 |
200 |
212 |
213 |
214 |
216 |
228 |
229 |
230 |
232 |
244 |
245 |
246 |
248 |
260 |
261 |
262 |
264 |
276 |
277 |
278 |
280 |
292 |
293 |
294 |
296 |
308 |
309 |
310 |
312 |
324 |
325 |
326 |
327 |
328 |
--------------------------------------------------------------------------------
/SwiftUI-BLE-Project.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7134F36B25C934A800DAD350 /* Peripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F36A25C934A800DAD350 /* Peripheral.swift */; };
11 | 7134F38425C93B7D00DAD350 /* CBCentralManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F37C25C93B7D00DAD350 /* CBCentralManagerMock.swift */; };
12 | 7134F38725C93B7D00DAD350 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F37F25C93B7D00DAD350 /* Mock.swift */; };
13 | 7134F38825C93B7D00DAD350 /* CBPeripheralMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F38025C93B7D00DAD350 /* CBPeripheralMock.swift */; };
14 | 7134F38925C93B7D00DAD350 /* CBPeripheralProtcolDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F38125C93B7D00DAD350 /* CBPeripheralProtcolDelegate.swift */; };
15 | 7134F38A25C93B7D00DAD350 /* Characteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F38225C93B7D00DAD350 /* Characteristic.swift */; };
16 | 7134F39325C93FE100DAD350 /* CoreBluetoothViewModelExtension+Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F39225C93FE100DAD350 /* CoreBluetoothViewModelExtension+Delegate.swift */; };
17 | 7134F39925C940DC00DAD350 /* ServiceCharacteristicsMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F39825C940DB00DAD350 /* ServiceCharacteristicsMock.swift */; };
18 | 7134F3A925CA3AC900DAD350 /* Service.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7134F3A825CA3AC900DAD350 /* Service.swift */; };
19 | 7134F3B625CA3F4300DAD350 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 7134F3B025CA3F4300DAD350 /* README.md */; };
20 | 715D90E425C9086500F19093 /* SwiftUI_BLE_ProjectApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D90E325C9086500F19093 /* SwiftUI_BLE_ProjectApp.swift */; };
21 | 715D90E625C9086500F19093 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D90E525C9086500F19093 /* ContentView.swift */; };
22 | 715D90E825C9086700F19093 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 715D90E725C9086700F19093 /* Assets.xcassets */; };
23 | 715D90EB25C9086700F19093 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 715D90EA25C9086700F19093 /* Preview Assets.xcassets */; };
24 | 715D90F825C90B6C00F19093 /* CoreBluetoothViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D90F725C90B6C00F19093 /* CoreBluetoothViewModel.swift */; };
25 | 715D910325C9229000F19093 /* ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D910225C9229000F19093 /* ListView.swift */; };
26 | 715D910725C9229A00F19093 /* DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 715D910625C9229A00F19093 /* DetailView.swift */; };
27 | 71A6E9A226D4115600B400BC /* CoreBluetoothViewModelExtension+SwiftUIView.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A6E9A126D4115600B400BC /* CoreBluetoothViewModelExtension+SwiftUIView.swift.swift */; };
28 | /* End PBXBuildFile section */
29 |
30 | /* Begin PBXFileReference section */
31 | 7134F36A25C934A800DAD350 /* Peripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Peripheral.swift; sourceTree = ""; };
32 | 7134F37C25C93B7D00DAD350 /* CBCentralManagerMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CBCentralManagerMock.swift; sourceTree = ""; };
33 | 7134F37F25C93B7D00DAD350 /* Mock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mock.swift; sourceTree = ""; };
34 | 7134F38025C93B7D00DAD350 /* CBPeripheralMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CBPeripheralMock.swift; sourceTree = ""; };
35 | 7134F38125C93B7D00DAD350 /* CBPeripheralProtcolDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CBPeripheralProtcolDelegate.swift; sourceTree = ""; };
36 | 7134F38225C93B7D00DAD350 /* Characteristic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Characteristic.swift; sourceTree = ""; };
37 | 7134F39225C93FE100DAD350 /* CoreBluetoothViewModelExtension+Delegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreBluetoothViewModelExtension+Delegate.swift"; sourceTree = ""; };
38 | 7134F39825C940DB00DAD350 /* ServiceCharacteristicsMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceCharacteristicsMock.swift; sourceTree = ""; };
39 | 7134F3A825CA3AC900DAD350 /* Service.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Service.swift; sourceTree = ""; };
40 | 7134F3B025CA3F4300DAD350 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
41 | 715D90E025C9086500F19093 /* SwiftUI-BLE-Project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SwiftUI-BLE-Project.app"; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 715D90E325C9086500F19093 /* SwiftUI_BLE_ProjectApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUI_BLE_ProjectApp.swift; sourceTree = ""; };
43 | 715D90E525C9086500F19093 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
44 | 715D90E725C9086700F19093 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
45 | 715D90EA25C9086700F19093 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
46 | 715D90EC25C9086700F19093 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | 715D90F725C90B6C00F19093 /* CoreBluetoothViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreBluetoothViewModel.swift; sourceTree = ""; };
48 | 715D910225C9229000F19093 /* ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListView.swift; sourceTree = ""; };
49 | 715D910625C9229A00F19093 /* DetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailView.swift; sourceTree = ""; };
50 | 71A6E9A126D4115600B400BC /* CoreBluetoothViewModelExtension+SwiftUIView.swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreBluetoothViewModelExtension+SwiftUIView.swift.swift"; sourceTree = ""; };
51 | /* End PBXFileReference section */
52 |
53 | /* Begin PBXFrameworksBuildPhase section */
54 | 715D90DD25C9086500F19093 /* Frameworks */ = {
55 | isa = PBXFrameworksBuildPhase;
56 | buildActionMask = 2147483647;
57 | files = (
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 7134F36925C9349400DAD350 /* Model */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 7134F37925C93B7D00DAD350 /* CoreBluetooth */,
68 | );
69 | path = Model;
70 | sourceTree = "";
71 | };
72 | 7134F37925C93B7D00DAD350 /* CoreBluetooth */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 71CC42732656078C004FBCD1 /* Delegate */,
76 | 7134F3BE25CA414800DAD350 /* Store */,
77 | 7134F37B25C93B7D00DAD350 /* Mock */,
78 | );
79 | path = CoreBluetooth;
80 | sourceTree = "";
81 | };
82 | 7134F37B25C93B7D00DAD350 /* Mock */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 7134F37F25C93B7D00DAD350 /* Mock.swift */,
86 | 7134F37C25C93B7D00DAD350 /* CBCentralManagerMock.swift */,
87 | 7134F38025C93B7D00DAD350 /* CBPeripheralMock.swift */,
88 | 7134F39825C940DB00DAD350 /* ServiceCharacteristicsMock.swift */,
89 | );
90 | path = Mock;
91 | sourceTree = "";
92 | };
93 | 7134F38F25C93C2C00DAD350 /* Navigation */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 715D90E325C9086500F19093 /* SwiftUI_BLE_ProjectApp.swift */,
97 | );
98 | path = Navigation;
99 | sourceTree = "";
100 | };
101 | 7134F39025C93C3D00DAD350 /* CoreBluetooth */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 715D90F725C90B6C00F19093 /* CoreBluetoothViewModel.swift */,
105 | 7134F39225C93FE100DAD350 /* CoreBluetoothViewModelExtension+Delegate.swift */,
106 | 71A6E9A126D4115600B400BC /* CoreBluetoothViewModelExtension+SwiftUIView.swift.swift */,
107 | );
108 | path = CoreBluetooth;
109 | sourceTree = "";
110 | };
111 | 7134F3BE25CA414800DAD350 /* Store */ = {
112 | isa = PBXGroup;
113 | children = (
114 | 7134F36A25C934A800DAD350 /* Peripheral.swift */,
115 | 7134F38225C93B7D00DAD350 /* Characteristic.swift */,
116 | 7134F3A825CA3AC900DAD350 /* Service.swift */,
117 | );
118 | path = Store;
119 | sourceTree = "";
120 | };
121 | 715D90D725C9086500F19093 = {
122 | isa = PBXGroup;
123 | children = (
124 | 7134F3B025CA3F4300DAD350 /* README.md */,
125 | 715D90E225C9086500F19093 /* SwiftUI-BLE-Project */,
126 | 715D90E125C9086500F19093 /* Products */,
127 | );
128 | sourceTree = "";
129 | };
130 | 715D90E125C9086500F19093 /* Products */ = {
131 | isa = PBXGroup;
132 | children = (
133 | 715D90E025C9086500F19093 /* SwiftUI-BLE-Project.app */,
134 | );
135 | name = Products;
136 | sourceTree = "";
137 | };
138 | 715D90E225C9086500F19093 /* SwiftUI-BLE-Project */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 7134F36925C9349400DAD350 /* Model */,
142 | 715D910D25C92DA000F19093 /* ViewModel */,
143 | 715D910125C9228400F19093 /* View */,
144 | 715D910E25C92DAF00F19093 /* Resouce */,
145 | 715D90EC25C9086700F19093 /* Info.plist */,
146 | 715D90E925C9086700F19093 /* Preview Content */,
147 | );
148 | path = "SwiftUI-BLE-Project";
149 | sourceTree = "";
150 | };
151 | 715D90E925C9086700F19093 /* Preview Content */ = {
152 | isa = PBXGroup;
153 | children = (
154 | 715D90EA25C9086700F19093 /* Preview Assets.xcassets */,
155 | );
156 | path = "Preview Content";
157 | sourceTree = "";
158 | };
159 | 715D910125C9228400F19093 /* View */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 715D90E525C9086500F19093 /* ContentView.swift */,
163 | 715D910225C9229000F19093 /* ListView.swift */,
164 | 715D910625C9229A00F19093 /* DetailView.swift */,
165 | );
166 | path = View;
167 | sourceTree = "";
168 | };
169 | 715D910D25C92DA000F19093 /* ViewModel */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 7134F39025C93C3D00DAD350 /* CoreBluetooth */,
173 | 7134F38F25C93C2C00DAD350 /* Navigation */,
174 | );
175 | path = ViewModel;
176 | sourceTree = "";
177 | };
178 | 715D910E25C92DAF00F19093 /* Resouce */ = {
179 | isa = PBXGroup;
180 | children = (
181 | 715D90E725C9086700F19093 /* Assets.xcassets */,
182 | );
183 | path = Resouce;
184 | sourceTree = "";
185 | };
186 | 71CC42732656078C004FBCD1 /* Delegate */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 7134F38125C93B7D00DAD350 /* CBPeripheralProtcolDelegate.swift */,
190 | );
191 | path = Delegate;
192 | sourceTree = "";
193 | };
194 | /* End PBXGroup section */
195 |
196 | /* Begin PBXNativeTarget section */
197 | 715D90DF25C9086500F19093 /* SwiftUI-BLE-Project */ = {
198 | isa = PBXNativeTarget;
199 | buildConfigurationList = 715D90EF25C9086700F19093 /* Build configuration list for PBXNativeTarget "SwiftUI-BLE-Project" */;
200 | buildPhases = (
201 | 715D90DC25C9086500F19093 /* Sources */,
202 | 715D90DD25C9086500F19093 /* Frameworks */,
203 | 715D90DE25C9086500F19093 /* Resources */,
204 | );
205 | buildRules = (
206 | );
207 | dependencies = (
208 | );
209 | name = "SwiftUI-BLE-Project";
210 | productName = "SwiftUI-BLE-Project";
211 | productReference = 715D90E025C9086500F19093 /* SwiftUI-BLE-Project.app */;
212 | productType = "com.apple.product-type.application";
213 | };
214 | /* End PBXNativeTarget section */
215 |
216 | /* Begin PBXProject section */
217 | 715D90D825C9086500F19093 /* Project object */ = {
218 | isa = PBXProject;
219 | attributes = {
220 | LastSwiftUpdateCheck = 1240;
221 | LastUpgradeCheck = 1240;
222 | TargetAttributes = {
223 | 715D90DF25C9086500F19093 = {
224 | CreatedOnToolsVersion = 12.4;
225 | };
226 | };
227 | };
228 | buildConfigurationList = 715D90DB25C9086500F19093 /* Build configuration list for PBXProject "SwiftUI-BLE-Project" */;
229 | compatibilityVersion = "Xcode 9.3";
230 | developmentRegion = en;
231 | hasScannedForEncodings = 0;
232 | knownRegions = (
233 | en,
234 | Base,
235 | );
236 | mainGroup = 715D90D725C9086500F19093;
237 | productRefGroup = 715D90E125C9086500F19093 /* Products */;
238 | projectDirPath = "";
239 | projectRoot = "";
240 | targets = (
241 | 715D90DF25C9086500F19093 /* SwiftUI-BLE-Project */,
242 | );
243 | };
244 | /* End PBXProject section */
245 |
246 | /* Begin PBXResourcesBuildPhase section */
247 | 715D90DE25C9086500F19093 /* Resources */ = {
248 | isa = PBXResourcesBuildPhase;
249 | buildActionMask = 2147483647;
250 | files = (
251 | 7134F3B625CA3F4300DAD350 /* README.md in Resources */,
252 | 715D90EB25C9086700F19093 /* Preview Assets.xcassets in Resources */,
253 | 715D90E825C9086700F19093 /* Assets.xcassets in Resources */,
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | };
257 | /* End PBXResourcesBuildPhase section */
258 |
259 | /* Begin PBXSourcesBuildPhase section */
260 | 715D90DC25C9086500F19093 /* Sources */ = {
261 | isa = PBXSourcesBuildPhase;
262 | buildActionMask = 2147483647;
263 | files = (
264 | 7134F38725C93B7D00DAD350 /* Mock.swift in Sources */,
265 | 7134F38425C93B7D00DAD350 /* CBCentralManagerMock.swift in Sources */,
266 | 7134F38925C93B7D00DAD350 /* CBPeripheralProtcolDelegate.swift in Sources */,
267 | 7134F3A925CA3AC900DAD350 /* Service.swift in Sources */,
268 | 715D90E625C9086500F19093 /* ContentView.swift in Sources */,
269 | 7134F36B25C934A800DAD350 /* Peripheral.swift in Sources */,
270 | 715D910325C9229000F19093 /* ListView.swift in Sources */,
271 | 7134F38825C93B7D00DAD350 /* CBPeripheralMock.swift in Sources */,
272 | 71A6E9A226D4115600B400BC /* CoreBluetoothViewModelExtension+SwiftUIView.swift.swift in Sources */,
273 | 7134F39325C93FE100DAD350 /* CoreBluetoothViewModelExtension+Delegate.swift in Sources */,
274 | 715D90E425C9086500F19093 /* SwiftUI_BLE_ProjectApp.swift in Sources */,
275 | 7134F39925C940DC00DAD350 /* ServiceCharacteristicsMock.swift in Sources */,
276 | 715D910725C9229A00F19093 /* DetailView.swift in Sources */,
277 | 7134F38A25C93B7D00DAD350 /* Characteristic.swift in Sources */,
278 | 715D90F825C90B6C00F19093 /* CoreBluetoothViewModel.swift in Sources */,
279 | );
280 | runOnlyForDeploymentPostprocessing = 0;
281 | };
282 | /* End PBXSourcesBuildPhase section */
283 |
284 | /* Begin XCBuildConfiguration section */
285 | 715D90ED25C9086700F19093 /* Debug */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | ALWAYS_SEARCH_USER_PATHS = NO;
289 | CLANG_ANALYZER_NONNULL = YES;
290 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
292 | CLANG_CXX_LIBRARY = "libc++";
293 | CLANG_ENABLE_MODULES = YES;
294 | CLANG_ENABLE_OBJC_ARC = YES;
295 | CLANG_ENABLE_OBJC_WEAK = YES;
296 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
297 | CLANG_WARN_BOOL_CONVERSION = YES;
298 | CLANG_WARN_COMMA = YES;
299 | CLANG_WARN_CONSTANT_CONVERSION = YES;
300 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
301 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
302 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
303 | CLANG_WARN_EMPTY_BODY = YES;
304 | CLANG_WARN_ENUM_CONVERSION = YES;
305 | CLANG_WARN_INFINITE_RECURSION = YES;
306 | CLANG_WARN_INT_CONVERSION = YES;
307 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
308 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
309 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
311 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
312 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
313 | CLANG_WARN_STRICT_PROTOTYPES = YES;
314 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
315 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
316 | CLANG_WARN_UNREACHABLE_CODE = YES;
317 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
318 | COPY_PHASE_STRIP = NO;
319 | DEBUG_INFORMATION_FORMAT = dwarf;
320 | ENABLE_STRICT_OBJC_MSGSEND = YES;
321 | ENABLE_TESTABILITY = YES;
322 | GCC_C_LANGUAGE_STANDARD = gnu11;
323 | GCC_DYNAMIC_NO_PIC = NO;
324 | GCC_NO_COMMON_BLOCKS = YES;
325 | GCC_OPTIMIZATION_LEVEL = 0;
326 | GCC_PREPROCESSOR_DEFINITIONS = (
327 | "DEBUG=1",
328 | "$(inherited)",
329 | );
330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
332 | GCC_WARN_UNDECLARED_SELECTOR = YES;
333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
334 | GCC_WARN_UNUSED_FUNCTION = YES;
335 | GCC_WARN_UNUSED_VARIABLE = YES;
336 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
337 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
338 | MTL_FAST_MATH = YES;
339 | ONLY_ACTIVE_ARCH = YES;
340 | SDKROOT = iphoneos;
341 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
342 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
343 | };
344 | name = Debug;
345 | };
346 | 715D90EE25C9086700F19093 /* Release */ = {
347 | isa = XCBuildConfiguration;
348 | buildSettings = {
349 | ALWAYS_SEARCH_USER_PATHS = NO;
350 | CLANG_ANALYZER_NONNULL = YES;
351 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
352 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
353 | CLANG_CXX_LIBRARY = "libc++";
354 | CLANG_ENABLE_MODULES = YES;
355 | CLANG_ENABLE_OBJC_ARC = YES;
356 | CLANG_ENABLE_OBJC_WEAK = YES;
357 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
358 | CLANG_WARN_BOOL_CONVERSION = YES;
359 | CLANG_WARN_COMMA = YES;
360 | CLANG_WARN_CONSTANT_CONVERSION = YES;
361 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
362 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
363 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
364 | CLANG_WARN_EMPTY_BODY = YES;
365 | CLANG_WARN_ENUM_CONVERSION = YES;
366 | CLANG_WARN_INFINITE_RECURSION = YES;
367 | CLANG_WARN_INT_CONVERSION = YES;
368 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
369 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
370 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
371 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
372 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
373 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
374 | CLANG_WARN_STRICT_PROTOTYPES = YES;
375 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
376 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
377 | CLANG_WARN_UNREACHABLE_CODE = YES;
378 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
379 | COPY_PHASE_STRIP = NO;
380 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
381 | ENABLE_NS_ASSERTIONS = NO;
382 | ENABLE_STRICT_OBJC_MSGSEND = YES;
383 | GCC_C_LANGUAGE_STANDARD = gnu11;
384 | GCC_NO_COMMON_BLOCKS = YES;
385 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
386 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
387 | GCC_WARN_UNDECLARED_SELECTOR = YES;
388 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
389 | GCC_WARN_UNUSED_FUNCTION = YES;
390 | GCC_WARN_UNUSED_VARIABLE = YES;
391 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
392 | MTL_ENABLE_DEBUG_INFO = NO;
393 | MTL_FAST_MATH = YES;
394 | SDKROOT = iphoneos;
395 | SWIFT_COMPILATION_MODE = wholemodule;
396 | SWIFT_OPTIMIZATION_LEVEL = "-O";
397 | VALIDATE_PRODUCT = YES;
398 | };
399 | name = Release;
400 | };
401 | 715D90F025C9086700F19093 /* Debug */ = {
402 | isa = XCBuildConfiguration;
403 | buildSettings = {
404 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
405 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
406 | CODE_SIGN_IDENTITY = "Apple Development";
407 | CODE_SIGN_STYLE = Automatic;
408 | CURRENT_PROJECT_VERSION = 2;
409 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUI-BLE-Project/Preview Content\"";
410 | DEVELOPMENT_TEAM = V838XQ8S9F;
411 | ENABLE_PREVIEWS = YES;
412 | INFOPLIST_FILE = "SwiftUI-BLE-Project/Info.plist";
413 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
414 | LD_RUNPATH_SEARCH_PATHS = (
415 | "$(inherited)",
416 | "@executable_path/Frameworks",
417 | );
418 | PRODUCT_BUNDLE_IDENTIFIER = "com.braveridge.SwiftUI-BLE-Project";
419 | PRODUCT_NAME = "$(TARGET_NAME)";
420 | PROVISIONING_PROFILE_SPECIFIER = "";
421 | SWIFT_VERSION = 5.0;
422 | TARGETED_DEVICE_FAMILY = "1,2";
423 | };
424 | name = Debug;
425 | };
426 | 715D90F125C9086700F19093 /* Release */ = {
427 | isa = XCBuildConfiguration;
428 | buildSettings = {
429 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
430 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
431 | CODE_SIGN_IDENTITY = "Apple Development";
432 | CODE_SIGN_STYLE = Automatic;
433 | CURRENT_PROJECT_VERSION = 2;
434 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUI-BLE-Project/Preview Content\"";
435 | DEVELOPMENT_TEAM = V838XQ8S9F;
436 | ENABLE_PREVIEWS = YES;
437 | INFOPLIST_FILE = "SwiftUI-BLE-Project/Info.plist";
438 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
439 | LD_RUNPATH_SEARCH_PATHS = (
440 | "$(inherited)",
441 | "@executable_path/Frameworks",
442 | );
443 | PRODUCT_BUNDLE_IDENTIFIER = "com.braveridge.SwiftUI-BLE-Project";
444 | PRODUCT_NAME = "$(TARGET_NAME)";
445 | PROVISIONING_PROFILE_SPECIFIER = "";
446 | SWIFT_VERSION = 5.0;
447 | TARGETED_DEVICE_FAMILY = "1,2";
448 | };
449 | name = Release;
450 | };
451 | /* End XCBuildConfiguration section */
452 |
453 | /* Begin XCConfigurationList section */
454 | 715D90DB25C9086500F19093 /* Build configuration list for PBXProject "SwiftUI-BLE-Project" */ = {
455 | isa = XCConfigurationList;
456 | buildConfigurations = (
457 | 715D90ED25C9086700F19093 /* Debug */,
458 | 715D90EE25C9086700F19093 /* Release */,
459 | );
460 | defaultConfigurationIsVisible = 0;
461 | defaultConfigurationName = Release;
462 | };
463 | 715D90EF25C9086700F19093 /* Build configuration list for PBXNativeTarget "SwiftUI-BLE-Project" */ = {
464 | isa = XCConfigurationList;
465 | buildConfigurations = (
466 | 715D90F025C9086700F19093 /* Debug */,
467 | 715D90F125C9086700F19093 /* Release */,
468 | );
469 | defaultConfigurationIsVisible = 0;
470 | defaultConfigurationName = Release;
471 | };
472 | /* End XCConfigurationList section */
473 | };
474 | rootObject = 715D90D825C9086500F19093 /* Project object */;
475 | }
476 |
--------------------------------------------------------------------------------