├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Example ├── Screenshots │ ├── demo_1.jpg │ └── example_1.png ├── Shared │ ├── AppleComputer.txt │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── BrowserState.swift │ ├── BrowserView.swift │ ├── DeviceView.swift │ ├── HardwareModel.swift │ ├── ServiceState.swift │ ├── ServiceView.swift │ └── SwiftBonjourApp.swift ├── SwiftBonjour │ ├── Info.plist │ └── SwiftBonjour.h ├── iOS │ └── Info.plist └── macOS │ ├── Info.plist │ └── macOS.entitlements ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── SwiftBonjour │ ├── BonjourBrowser.swift │ ├── BonjourLogger.swift │ ├── BonjourResolver.swift │ ├── BonjourServer.swift │ ├── IPAddress+Ext.swift │ ├── NetworkService+Ext.swift │ ├── ServiceType.swift │ └── SwiftBonjour.swift ├── SwiftBonjour.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── swiftpm │ └── Package.resolved └── SwiftBonjourExample.xcodeproj ├── project.pbxproj └── xcshareddata └── xcschemes ├── SwiftBonjour Browser (iOS).xcscheme ├── SwiftBonjour Browser (macOS).xcscheme ├── SwiftBonjour Service (iOS).xcscheme └── SwiftBonjour Service (macOS).xcscheme /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | # Created by https://www.toptal.com/developers/gitignore/api/macos,xcode,swift 7 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,xcode,swift 8 | 9 | ### macOS ### 10 | # General 11 | .DS_Store 12 | .AppleDouble 13 | .LSOverride 14 | 15 | # Icon must end with two \r 16 | Icon 17 | 18 | # Thumbnails 19 | ._* 20 | 21 | # Files that might appear in the root of a volume 22 | .DocumentRevisions-V100 23 | .fseventsd 24 | .Spotlight-V100 25 | .TemporaryItems 26 | .Trashes 27 | .VolumeIcon.icns 28 | .com.apple.timemachine.donotpresent 29 | 30 | # Directories potentially created on remote AFP share 31 | .AppleDB 32 | .AppleDesktop 33 | Network Trash Folder 34 | Temporary Items 35 | .apdisk 36 | 37 | ### Swift ### 38 | # Xcode 39 | # 40 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 41 | 42 | ## User settings 43 | xcuserdata/ 44 | 45 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 46 | *.xcscmblueprint 47 | *.xccheckout 48 | 49 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 50 | build/ 51 | DerivedData/ 52 | *.moved-aside 53 | *.pbxuser 54 | !default.pbxuser 55 | *.mode1v3 56 | !default.mode1v3 57 | *.mode2v3 58 | !default.mode2v3 59 | *.perspectivev3 60 | !default.perspectivev3 61 | 62 | ## Obj-C/Swift specific 63 | *.hmap 64 | 65 | ## App packaging 66 | *.ipa 67 | *.dSYM.zip 68 | *.dSYM 69 | 70 | ## Playgrounds 71 | timeline.xctimeline 72 | playground.xcworkspace 73 | 74 | # Swift Package Manager 75 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 76 | # Packages/ 77 | # Package.pins 78 | # Package.resolved 79 | # *.xcodeproj 80 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 81 | # hence it is not needed unless you have added a package configuration file to your project 82 | # .swiftpm 83 | 84 | .build/ 85 | 86 | # CocoaPods 87 | # We recommend against adding the Pods directory to your .gitignore. However 88 | # you should judge for yourself, the pros and cons are mentioned at: 89 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 90 | # Pods/ 91 | # Add this line if you want to avoid checking in source code from the Xcode workspace 92 | # *.xcworkspace 93 | 94 | # Carthage 95 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 96 | # Carthage/Checkouts 97 | 98 | Carthage/Build/ 99 | 100 | # Add this lines if you are using Accio dependency management (Deprecated since Xcode 12) 101 | # Dependencies/ 102 | # .accio/ 103 | 104 | # fastlane 105 | # It is recommended to not store the screenshots in the git repo. 106 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 107 | # For more information about the recommended setup visit: 108 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 109 | 110 | fastlane/report.xml 111 | fastlane/Preview.html 112 | fastlane/screenshots/**/*.png 113 | fastlane/test_output 114 | 115 | # Code Injection 116 | # After new code Injection tools there's a generated folder /iOSInjectionProject 117 | # https://github.com/johnno1962/injectionforxcode 118 | 119 | iOSInjectionProject/ 120 | 121 | ### Xcode ### 122 | # Xcode 123 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 124 | 125 | 126 | 127 | 128 | ## Gcc Patch 129 | /*.gcno 130 | 131 | ### Xcode Patch ### 132 | *.xcodeproj/* 133 | !*.xcodeproj/project.pbxproj 134 | !*.xcodeproj/xcshareddata/ 135 | !*.xcworkspace/contents.xcworkspacedata 136 | **/xcshareddata/WorkspaceSettings.xcsettings 137 | 138 | # End of https://www.toptal.com/developers/gitignore/api/macos,xcode,swift 139 | 140 | *.resolved 141 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Screenshots/demo_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessica/SwiftBonjour/aec073a852b0308904ce295c387e9669631d9d1c/Example/Screenshots/demo_1.jpg -------------------------------------------------------------------------------- /Example/Screenshots/example_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessica/SwiftBonjour/aec073a852b0308904ce295c387e9669631d9d1c/Example/Screenshots/example_1.png -------------------------------------------------------------------------------- /Example/Shared/AppleComputer.txt: -------------------------------------------------------------------------------- 1 | Apple Computer|Model Identifier 2 | eMac G4/700|PowerMac4,4 3 | eMac G4/800|PowerMac4,4 4 | eMac G4/800 (ATI)|PowerMac4,4 5 | eMac G4/1.0 (ATI)|PowerMac4,4 6 | eMac G4/1.25 (USB 2.0)|PowerMac6,4 7 | eMac G4/1.42 (2005)|PowerMac6,4 8 | iBook G3/300 (Original/Clamshell)|PowerBook2,1 9 | iBook G3/366 SE (Original/Clamshell)|PowerBook2,1 10 | iBook G3/366 (Firewire/Clamshell)|PowerBook2,2 11 | iBook G3/466 SE (Firewire/Clamshell)|PowerBook2,2 12 | iBook G3/500 (Dual USB - Tr)|PowerBook4,1 13 | iBook G3/500 (Late 2001 - Tr)|PowerBook4,1 14 | iBook G3/600 (Late 2001 - Tr)|PowerBook4,1 15 | iBook G3/600 14-Inch (Early 2002 - Tr)|PowerBook4,2 16 | iBook G3/600 (16 VRAM - Tr)|PowerBook4,3 17 | iBook G3/700 (16 VRAM - Tr)|PowerBook4,3 18 | iBook G3/700 14-Inch (16 VRAM - Tr)|PowerBook4,3 19 | iBook G3/700 (16 VRAM - Op)|PowerBook4,3 20 | iBook G3/800 (32 VRAM - Tr)|PowerBook4,3 21 | iBook G3/800 14-Inch (32 VRAM - Tr)|PowerBook4,3 22 | iBook G3/800 (Early 2003 - Op)|PowerBook4,3 23 | iBook G3/900 (Early 2003 - Op)|PowerBook4,3 24 | iBook G3/900 14-Inch (Early 2003 - Op)|PowerBook4,3 25 | iBook G4/800 12-Inch (Original - Op)|PowerBook6,3 26 | iBook G4/933 14-Inch (Original - Op)|PowerBook6,3 27 | iBook G4/1.0 14-Inch (Original - Op)|PowerBook6,3 28 | iBook G4/1.0 12-Inch (Early 2004 - Op)|PowerBook6,5 29 | iBook G4/1.0 14-Inch (Early 2004 - Op)|PowerBook6,5 30 | iBook G4/1.2 14-Inch (Early 2004 - Op)|PowerBook6,5 31 | iBook G4/1.2 12-Inch (Late 2004 - Op)|PowerBook6,5 32 | iBook G4/1.33 14-Inch (Late 2004 - Op)|PowerBook6,5 33 | iBook G4/1.33 12-Inch (Mid-2005 - Op)|PowerBook6,7 34 | iBook G4/1.42 14-Inch (Mid-2005 - Op)|PowerBook6,7 35 | iMac 17-Inch "Core Duo" 1.83|iMac4,1 36 | iMac 17-Inch "Core Duo" 1.83 (IG)|iMac4,2 37 | iMac 17-Inch "Core 2 Duo" 1.83 (IG)|iMac5,2 38 | iMac 17-Inch "Core 2 Duo" 2.0|iMac5,1 39 | iMac 17-Inch "Core 2 Duo" 2.16|iMac5,1 40 | iMac 20-Inch "Core Duo" 2.0|iMac4,1 41 | iMac 20-Inch "Core 2 Duo" 2.16|iMac5,1 42 | iMac 20-Inch "Core 2 Duo" 2.33|iMac5,1 43 | iMac 20-Inch "Core 2 Duo" 2.0 (Al)|iMac7,1 44 | iMac 20-Inch "Core 2 Duo" 2.4 (Al)|iMac7,1 45 | iMac 20-Inch "Core 2 Duo" 2.4 (Early 2008)|iMac8,1 46 | iMac 20-Inch "Core 2 Duo" 2.66 (Early 2008)|iMac8,1 47 | iMac 20-Inch "Core 2 Duo" 2.66 (Early 2009)|iMac9,1 48 | iMac 20-Inch "Core 2 Duo" 2.0 (Mid-2009)|iMac9,1 49 | iMac 20-Inch "Core 2 Duo" 2.26 (Mid-2009)|iMac9,1 50 | iMac 21.5-Inch "Core 2 Duo" 3.06 (Late 2009)|iMac10,1 51 | iMac 21.5-Inch "Core 2 Duo" 3.33 (Late 2009)|iMac10,1 52 | iMac 21.5-Inch "Core i3" 3.06 (Mid-2010)|iMac11,2 53 | iMac 21.5-Inch "Core i3" 3.2 (Mid-2010)|iMac11,2 54 | iMac 21.5-Inch "Core i5" 3.6 (Mid-2010)|iMac11,2 55 | iMac 21.5-Inch "Core i5" 2.5 (Mid-2011)|iMac12,1 56 | iMac 21.5-Inch "Core i5" 2.7 (Mid-2011)|iMac12,1 57 | iMac 21.5-Inch "Core i7" 2.8 (Mid-2011)|iMac12,1 58 | iMac 21.5-Inch "Core i3" 3.1 (Late 2011)|iMac12,1 59 | iMac 21.5-Inch "Core i5" 2.7 (Late 2012)|iMac13,1 60 | iMac 21.5-Inch "Core i5" 2.9 (Late 2012)|iMac13,1 61 | iMac 21.5-Inch "Core i7" 3.1 (Late 2012)|iMac13,1 62 | iMac 21.5-Inch "Core i3" 3.3 (Early 2013)|iMac13,1 63 | iMac 21.5-Inch "Core i5" 2.7 (Late 2013)|iMac14,1 64 | iMac 21.5-Inch "Core i5" 2.9 (Late 2013)|iMac14,3 65 | iMac 21.5-Inch "Core i7" 3.1 (Late 2013)|iMac14,3 66 | iMac 21.5-Inch "Core i5" 1.4 (Mid-2014)|iMac14,4 67 | iMac 21.5-Inch "Core i5" 1.6 (Late 2015)|iMac16,1 68 | iMac 21.5-Inch "Core i5" 2.8 (Late 2015)|iMac16,2 69 | iMac 21.5-Inch "Core i5" 3.1 (4K, Late 2015)|iMac16,2 70 | iMac 21.5-Inch "Core i7" 3.3 (4K, Late 2015)|iMac16,2 71 | iMac 21.5-Inch "Core i5" 2.3 (Mid-2017)|iMac18,1 72 | iMac 21.5-Inch "Core i5" 3.0 (4K, Mid-2017)|iMac18,2 73 | iMac 21.5-Inch "Core i5" 3.4 (4K, Mid-2017)|iMac18,2 74 | iMac 21.5-Inch "Core i7" 3.6 (4K, Mid-2017)|iMac18,2 75 | iMac 21.5-Inch "Core i3" 3.6 (4K, 2019)|iMac19,2 76 | iMac 21.5-Inch "Core i5" 3.0 (4K, 2019)|iMac19,2 77 | iMac 21.5-Inch "Core i7" 3.2 (4K, 2019)|iMac19,2 78 | iMac 24-Inch "Core 2 Duo" 2.16|iMac6,1 79 | iMac 24-Inch "Core 2 Duo" 2.33|iMac6,1 80 | iMac 24-Inch "Core 2 Duo" 2.4 (Al)|iMac7,1 81 | iMac 24-Inch "Core 2 Extreme" 2.8 (Al)|iMac7,1 82 | iMac 24-Inch "Core 2 Duo" 2.8 (Early 2008)|iMac8,1 83 | iMac 24-Inch "Core 2 Duo" 3.06 (Early 2008)|iMac8,1 84 | iMac 24-Inch "Core 2 Duo" 2.66 (Early 2009)|iMac9,1 85 | iMac 24-Inch "Core 2 Duo" 2.93 (Early 2009)|iMac9,1 86 | iMac 24-Inch "Core 2 Duo" 3.06 (Early 2009)|iMac9,1 87 | iMac 27-Inch "Core 2 Duo" 3.06 (Late 2009)|iMac10,1 88 | iMac 27-Inch "Core 2 Duo" 3.33 (Late 2009)|iMac10,1 89 | iMac 27-Inch "Core i5" 2.66 (Late 2009)|iMac11,1 90 | iMac 27-Inch "Core i7" 2.8 (Late 2009)|iMac11,1 91 | iMac 27-Inch "Core i3" 3.2 (Mid-2010)|iMac11,3 92 | iMac 27-Inch "Core i5" 2.8 (Mid-2010)|iMac11,3 93 | iMac 27-Inch "Core i5" 3.6 (Mid-2010)|iMac11,3 94 | iMac 27-Inch "Core i7" 2.93 (Mid-2010)|iMac11,3 95 | iMac 27-Inch "Core i5" 2.7 (Mid-2011)|iMac12,2 96 | iMac 27-Inch "Core i5" 3.1 (Mid-2011)|iMac12,2 97 | iMac 27-Inch "Core i7" 3.4 (Mid-2011)|iMac12,2 98 | iMac 27-Inch "Core i5" 2.9 (Late 2012)|iMac13,2 99 | iMac 27-Inch "Core i5" 3.2 (Late 2012)|iMac13,2 100 | iMac 27-Inch "Core i7" 3.4 (Late 2012)|iMac13,2 101 | iMac 27-Inch "Core i5" 3.2 (Late 2013)|iMac14,2 102 | iMac 27-Inch "Core i5" 3.4 (Late 2013)|iMac14,2 103 | iMac 27-Inch "Core i7" 3.5 (Late 2013)|iMac14,2 104 | iMac 27-Inch "Core i5" 3.5 (5K, Late 2014)|iMac15,1 105 | iMac 27-Inch "Core i7" 4.0 (5K, Late 2014)|iMac15,1 106 | iMac 27-Inch "Core i5" 3.3 (5K, Mid-2015)|iMac15,1 107 | iMac 27-Inch "Core i5" 3.2 (5K, Late 2015)|iMac17,1 108 | iMac 27-Inch "Core i5" 3.3 (5K, Late 2015)|iMac17,1 109 | iMac 27-Inch "Core i7" 4.0 (5K, Late 2015)|iMac17,1 110 | iMac 27-Inch "Core i5" 3.4 (5K, Mid-2017)|iMac18,3 111 | iMac 27-Inch "Core i5" 3.5 (5K, Mid-2017)|iMac18,3 112 | iMac 27-Inch "Core i5" 3.8 (5K, Mid-2017)|iMac18,3 113 | iMac 27-Inch "Core i7" 4.2 (5K, Mid-2017)|iMac18,3 114 | iMac 27-Inch "Core i5" 3.0 (5K, 2019)|iMac19,1 115 | iMac 27-Inch "Core i5" 3.1 (5K, 2019)|iMac19,1 116 | iMac 27-Inch "Core i5" 3.7 (5K, 2019)|iMac19,1 117 | iMac 27-Inch "Core i9" 3.6 (5K, 2019)|iMac19,1 118 | iMac G3 233 Original - Bondi (Rev. A & B)|iMac,1 119 | iMac G3 266 (Fruit Colors)|iMac,1 120 | iMac G3 333 (Fruit Colors)|iMac,1 121 | iMac G3 350 (Slot Loading - Blueberry)|PowerMac2,1 122 | iMac G3 400 DV (Slot Loading - Fruit)|PowerMac2,1 123 | iMac G3 400 DV SE (Slot Loading)|PowerMac2,1 124 | iMac G3 350 (Summer 2000 - Indigo)|PowerMac2,2 125 | iMac G3 400 DV (Summer 2000 - I/R)|PowerMac2,2 126 | iMac G3 450 DV+ (Summer 2000)|PowerMac2,2 127 | iMac G3 500 DV SE (Summer 2000)|PowerMac2,2 128 | iMac G3 400 (Early 2001 - Indigo)|PowerMac4,1 129 | iMac G3 500 (Early 2001 - Flower/Blue)|PowerMac4,1 130 | iMac G3 600 SE (Early 2001)|PowerMac4,1 131 | iMac G3 500 (Summer 2001 - I/S)|PowerMac4,1 132 | iMac G3 600 (Summer 2001)|PowerMac4,1 133 | iMac G3 700 SE (Summer 2001)|PowerMac4,1 134 | iMac G4 700 (Flat Panel)|PowerMac4,2 135 | iMac G4 800 (Flat Panel)|PowerMac4,2 136 | iMac G4 800 17" (Flat Panel)|PowerMac4,5 137 | iMac G4 800 - X Only (Flat Panel)|PowerMac4,2 138 | iMac G4 1.0 17" (Flat Panel)|PowerMac6,1 139 | iMac G4 1.0 15" "FP" (USB 2.0)|PowerMac6,3* 140 | iMac G4 1.25 17" "FP" (USB 2.0)|PowerMac6,3 141 | iMac G4 1.25 20" "FP" (USB 2.0)|PowerMac6,3 142 | iMac G5 1.6 17"|PowerMac8,1 143 | iMac G5 1.8 17"|PowerMac8,1 144 | iMac G5 1.8 20"|PowerMac8,1 145 | iMac G5 1.8 17" (ALS)|PowerMac8,2 146 | iMac G5 2.0 17" (ALS)|PowerMac8,2 147 | iMac G5 2.0 20" (ALS)|PowerMac8,2 148 | iMac G5 1.9 17" (iSight)|PowerMac12,1 149 | iMac G5 2.1 20" (iSight)|PowerMac12,1 150 | iMac Pro "8-Core" 3.2 27-Inch (5K, Late 2017)|iMacPro1,1 151 | iMac Pro "10-Core" 3.0 27-Inch (5K, Late 2017)|iMacPro1,1 152 | iMac Pro "14-Core" 2.5 27-Inch (5K, Late 2017)|iMacPro1,1 153 | iMac Pro "18-Core" 2.3 27-Inch (5K, Late 2017)|iMacPro1,1 154 | Mac mini G4/1.25|PowerMac10,1 155 | Mac mini G4/1.42|PowerMac10,1 156 | Mac mini G4/1.33|PowerMac10,2 157 | Mac mini G4/1.5|PowerMac10,2 158 | Mac mini "Core Solo" 1.5|Macmini1,1 159 | Mac mini "Core Duo" 1.66|Macmini1,1 160 | Mac mini "Core Duo" 1.83|Macmini1,1 161 | Mac mini "Core 2 Duo" 1.83|Macmini2,1 162 | Mac mini "Core 2 Duo" 2.0|Macmini2,1 163 | Mac mini "Core 2 Duo" 2.0 (Early 2009)|Macmini3,1 164 | Mac mini "Core 2 Duo" 2.26 (Early 2009)|Macmini3,1 165 | Mac mini "Core 2 Duo" 2.26 (Late 2009)|Macmini3,1 166 | Mac mini "Core 2 Duo" 2.53 (Late 2009)|Macmini3,1 167 | Mac mini "Core 2 Duo" 2.66 (Late 2009)|Macmini3,1 168 | Mac mini "Core 2 Duo" 2.53 (Server)|Macmini3,1 169 | Mac mini "Core 2 Duo" 2.4 (Mid-2010)|Macmini4,1 170 | Mac mini "Core 2 Duo" 2.66 (Mid-2010)|Macmini4,1 171 | Mac mini "Core 2 Duo" 2.66 (Server)|Macmini4,1 172 | Mac mini "Core i5" 2.3 (Mid-2011)|Macmini5,1 173 | Mac mini "Core i5" 2.5 (Mid-2011)|Macmini5,2 174 | Mac mini "Core i7" 2.7 (Mid-2011)|Macmini5,2 175 | Mac mini "Core i7" 2.0 (Mid-2011/Server)|Macmini5,3 176 | Mac mini "Core i5" 2.5 (Late 2012)|Macmini6,1 177 | Mac mini "Core i7" 2.3 (Late 2012)|Macmini6,2 178 | Mac mini "Core i7" 2.6 (Late 2012)|Macmini6,2 179 | Mac mini "Core i7" 2.3 (Late 2012/Server)|Macmini6,2 180 | Mac mini "Core i7" 2.6 (Late 2012/Server)|Macmini6,2 181 | Mac mini "Core i5" 1.4 (Late 2014)|Macmini7,1 182 | Mac mini "Core i5" 2.6 (Late 2014)|Macmini7,1 183 | Mac mini "Core i5" 2.8 (Late 2014)|Macmini7,1 184 | Mac mini "Core i7" 3.0 (Late 2014)|Macmini7,1 185 | Mac mini "Core i3" 3.6 (Late 2018)|Macmini8,1 186 | Mac mini "Core i5" 3.0 (Late 2018)|Macmini8,1 187 | Mac mini "Core i7" 3.2 (Late 2018)|Macmini8,1 188 | Mac Pro "Quad Core" 2.0 (Original)|MacPro1,1* 189 | Mac Pro "Quad Core" 2.66 (Original)|MacPro1,1* 190 | Mac Pro "Quad Core" 3.0 (Original)|MacPro1,1* 191 | Mac Pro "Eight Core" 3.0 (2,1)|MacPro2,1 192 | Mac Pro "Quad Core" 2.8 (2008)|MacPro3,1 193 | Mac Pro "Eight Core" 2.8 (2008)|MacPro3,1 194 | Mac Pro "Eight Core" 3.0 (2008)|MacPro3,1 195 | Mac Pro "Eight Core" 3.2 (2008)|MacPro3,1 196 | Mac Pro "Quad Core" 2.66 (2009/Nehalem)|MacPro4,1 197 | Mac Pro "Quad Core" 2.93 (2009/Nehalem)|MacPro4,1 198 | Mac Pro "Quad Core" 3.33 (2009/Nehalem)|MacPro4,1 199 | Mac Pro "Eight Core" 2.26 (2009/Nehalem)|MacPro4,1 200 | Mac Pro "Eight Core" 2.66 (2009/Nehalem)|MacPro4,1 201 | Mac Pro "Eight Core" 2.93 (2009/Nehalem)|MacPro4,1 202 | Mac Pro "Quad Core" 2.8 (2010/Nehalem)|MacPro5,1 203 | Mac Pro "Quad Core" 3.2 (2010/Nehalem)|MacPro5,1 204 | Mac Pro "Six Core" 3.33 (2010/Westmere)|MacPro5,1 205 | Mac Pro "Eight Core" 2.4 (2010/Westmere)|MacPro5,1 206 | Mac Pro "Twelve Core" 2.66 (2010/Westmere)|MacPro5,1 207 | Mac Pro "Twelve Core" 2.93 (2010/Westmere)|MacPro5,1 208 | Mac Pro "Quad Core" 2.8 (Server 2010)|MacPro5,1 209 | Mac Pro "Quad Core" 3.2 (Server 2010)|MacPro5,1 210 | Mac Pro "Six Core" 3.33 (Server 2010)|MacPro5,1 211 | Mac Pro "Eight Core" 2.4 (Server 2010)|MacPro5,1 212 | Mac Pro "Twelve Core" 2.66 (Server 2010)|MacPro5,1 213 | Mac Pro "Twelve Core" 2.93 (Server 2010)|MacPro5,1 214 | Mac Pro "Quad Core" 3.2 (2012/Nehalem)|MacPro5,1 215 | Mac Pro "Six Core" 3.33 (2012/Westmere)|MacPro5,1 216 | Mac Pro "Twelve Core" 2.4 (2012/Westmere)|MacPro5,1 217 | Mac Pro "Twelve Core" 2.66 (2012/Westmere)|MacPro5,1 218 | Mac Pro "Twelve Core" 3.06 (2012/Westmere)|MacPro5,1 219 | Mac Pro "Quad Core" 3.2 (Server 2012)|MacPro5,1 220 | Mac Pro "Six Core" 3.33 (Server 2012)|MacPro5,1 221 | Mac Pro "Twelve Core" 2.4 (Server 2012)|MacPro5,1 222 | Mac Pro "Twelve Core" 2.66 (Server 2012)|MacPro5,1 223 | Mac Pro "Twelve Core" 3.06 (Server 2012)|MacPro5,1 224 | Mac Pro "Quad Core" 3.7 (Late 2013)|MacPro6,1 225 | Mac Pro "Six Core" 3.5 (Late 2013)|MacPro6,1 226 | Mac Pro "Eight Core" 3.0 (Late 2013)|MacPro6,1 227 | Mac Pro "Twelve Core" 2.7 (Late 2013)|MacPro6,1 228 | Mac Pro "Eight Core" 3.5 (2019)|MacPro7,1 229 | Mac Pro "12-Core" 3.3 (2019)|MacPro7,1 230 | Mac Pro "16-Core" 3.2 (2019)|MacPro7,1 231 | Mac Pro "24-Core" 2.7 (2019)|MacPro7,1 232 | Mac Pro "28-Core" 2.5 (2019)|MacPro7,1 233 | Mac Pro "Eight Core" 3.5 (2019 - Rack)|MacPro7,1 234 | Mac Pro "12-Core" 3.3 (2019 - Rack)|MacPro7,1 235 | Mac Pro "16-Core" 3.2 (2019 - Rack)|MacPro7,1 236 | Mac Pro "24-Core" 2.7 (2019 - Rack)|MacPro7,1 237 | Mac Pro "28-Core" 2.5 (2019 - Rack)|MacPro7,1 238 | Mac Server G3 233 Minitower|N/A* 239 | Mac Server G3 266 Minitower|N/A* 240 | Mac Server G3 300 Minitower|N/A* 241 | Mac Server G3 333 Minitower|N/A* 242 | Mac Server G3 350 (Blue & White)|PowerMac1,1 243 | Mac Server G3 400 (Blue & White)|PowerMac1,1 244 | Mac Server G3 450 (Blue & White)|PowerMac1,1 245 | Mac Server G4 350 (AGP)|PowerMac3,1 246 | Mac Server G4 400 (AGP)|PowerMac3,1 247 | Mac Server G4 450 (AGP)|PowerMac3,1 248 | Mac Server G4 500 (AGP)|PowerMac3,1 249 | Mac Server G4 450 DP (Gigabit)|PowerMac3,3 250 | Mac Server G4 500 DP (Gigabit)|PowerMac3,3 251 | Mac Server G4 533 (Digital Audio)|PowerMac3,4 252 | Mac Server G4 533 DP (Digital Audio)|PowerMac3,4 253 | Mac Server G4 733 (Quicksilver)|PowerMac3,5 254 | Mac Server G4 800 DP (Quicksilver)|PowerMac3,5 255 | Mac Server G4 933 (QS 2002)|PowerMac3,5 256 | Mac Server G4 1.0 DP (QS 2002)|PowerMac3,5 257 | Mac Server G4 1.0 DP (MDD)|PowerMac3,6 258 | Mac Server G4 1.25 DP (MDD)|PowerMac3,6 259 | MacBook "Core Duo" 1.83 13"|MacBook1,1 260 | MacBook "Core Duo" 2.0 13" (White)|MacBook1,1 261 | MacBook "Core Duo" 2.0 13" (Black)|MacBook1,1 262 | MacBook "Core 2 Duo" 1.83 13"|MacBook2,1 263 | MacBook "Core 2 Duo" 2.0 13" (White/06)|MacBook2,1 264 | MacBook "Core 2 Duo" 2.0 13" (Black)|MacBook2,1 265 | MacBook "Core 2 Duo" 2.0 13" (White/07)|MacBook2,1 266 | MacBook "Core 2 Duo" 2.16 13" (White)|MacBook2,1 267 | MacBook "Core 2 Duo" 2.16 13" (Black)|MacBook2,1 268 | MacBook "Core 2 Duo" 2.0 13" (White-SR)|MacBook3,1 269 | MacBook "Core 2 Duo" 2.2 13" (White-SR)|MacBook3,1 270 | MacBook "Core 2 Duo" 2.2 13" (Black-SR)|MacBook3,1 271 | MacBook "Core 2 Duo" 2.1 13" (White-08)|MacBook4,1 272 | MacBook "Core 2 Duo" 2.4 13" (White-08)|MacBook4,1 273 | MacBook "Core 2 Duo" 2.4 13" (Black-08)|MacBook4,1 274 | MacBook "Core 2 Duo" 2.0 13" (Unibody)|MacBook5,1 275 | MacBook "Core 2 Duo" 2.4 13" (Unibody)|MacBook5,1 276 | MacBook "Core 2 Duo" 2.0 13" (White-09)|MacBook5,2 277 | MacBook "Core 2 Duo" 2.13 13" (White-09)|MacBook5,2 278 | MacBook "Core 2 Duo" 2.26 13" (Uni/Late 09)|MacBook6,1 279 | MacBook "Core 2 Duo" 2.4 13" (Mid-2010)|MacBook7,1 280 | MacBook "Core M" 1.1 12" (Early 2015)|MacBook8,1 281 | MacBook "Core M" 1.2 12" (Early 2015)|MacBook8,1 282 | MacBook "Core M" 1.3 12" (Early 2015)|MacBook8,1 283 | MacBook "Core m3" 1.1 12" (Early 2016)|MacBook9,1 284 | MacBook "Core m5" 1.2 12" (Early 2016)|MacBook9,1 285 | MacBook "Core m7" 1.3 12" (Early 2016)|MacBook9,1 286 | MacBook "Core m3" 1.2 12" (Mid-2017)|MacBook10,1 287 | MacBook "Core i5" 1.3 12" (Mid-2017)|MacBook10,1 288 | MacBook "Core i7" 1.4 12" (Mid-2017)|MacBook10,1 289 | MacBook Air "Core 2 Duo" 1.6 13" (Original)|MacBookAir1,1 290 | MacBook Air "Core 2 Duo" 1.8 13" (Original)|MacBookAir1,1 291 | MacBook Air "Core 2 Duo" 1.6 13" (NVIDIA)|MacBookAir2,1 292 | MacBook Air "Core 2 Duo" 1.86 13" (NVIDIA)|MacBookAir2,1 293 | MacBook Air "Core 2 Duo" 1.86 13" (Mid-09)|MacBookAir2,1 294 | MacBook Air "Core 2 Duo" 2.13 13" (Mid-09)|MacBookAir2,1 295 | MacBook Air "Core 2 Duo" 1.4 11" (Late '10)|MacBookAir3,1 296 | MacBook Air "Core 2 Duo" 1.6 11" (Late '10)|MacBookAir3,1 297 | MacBook Air "Core 2 Duo" 1.86 13" (Late '10)|MacBookAir3,2 298 | MacBook Air "Core 2 Duo" 2.13 13" (Late '10)|MacBookAir3,2 299 | MacBook Air "Core i5" 1.6 11" (Mid-2011)|MacBookAir4,1 300 | MacBook Air "Core i7" 1.8 11" (Mid-2011)|MacBookAir4,1 301 | MacBook Air "Core i5" 1.7 13" (Mid-2011)|MacBookAir4,2 302 | MacBook Air "Core i7" 1.8 13" (Mid-2011)|MacBookAir4,2 303 | MacBook Air "Core i5" 1.6 13" (Edu Only)|MacBookAir4,2 304 | MacBook Air "Core i5" 1.7 11" (Mid-2012)|MacBookAir5,1 305 | MacBook Air "Core i7" 2.0 11" (Mid-2012)|MacBookAir5,1 306 | MacBook Air "Core i5" 1.7 13" (Edu Only)|MacBookAir5,2 307 | MacBook Air "Core i5" 1.8 13" (Mid-2012)|MacBookAir5,2 308 | MacBook Air "Core i7" 2.0 13" (Mid-2012)|MacBookAir5,2 309 | MacBook Air "Core i5" 1.3 11" (Mid-2013)|MacBookAir6,1 310 | MacBook Air "Core i7" 1.7 11" (Mid-2013)|MacBookAir6,1 311 | MacBook Air "Core i5" 1.3 13" (Mid-2013)|MacBookAir6,2 312 | MacBook Air "Core i7" 1.7 13" (Mid-2013)|MacBookAir6,2 313 | MacBook Air "Core i5" 1.4 11" (Early 2014)|MacBookAir6,1 314 | MacBook Air "Core i7" 1.7 11" (Early 2014)|MacBookAir6,1 315 | MacBook Air "Core i5" 1.4 13" (Early 2014)|MacBookAir6,2 316 | MacBook Air "Core i7" 1.7 13" (Early 2014)|MacBookAir6,2 317 | MacBook Air "Core i5" 1.6 11" (Early 2015)|MacBookAir7,1 318 | MacBook Air "Core i7" 2.2 11" (Early 2015)|MacBookAir7,1 319 | MacBook Air "Core i5" 1.6 13" (Early 2015)|MacBookAir7,2 320 | MacBook Air "Core i7" 2.2 13" (Early 2015)|MacBookAir7,2 321 | MacBook Air "Core i5" 1.8 13" (2017*)|MacBookAir7,2 322 | MacBook Air "Core i7" 2.2 13" (2017*)|MacBookAir7,2 323 | MacBook Air "Core i5" 1.6 13" (Late 2018)|MacBookAir8,1 324 | MacBook Air "Core i5" 1.6 13" (True Tone, 2019)|MacBookAir8,2 325 | MacBook Air "Core i3" 1.1 13" (Scissor, 2020)|MacBookAir9,1 326 | MacBook Air "Core i5" 1.1 13" (Scissor, 2020)|MacBookAir9,1 327 | MacBook Air "Core i7" 1.2 13" (Scissor, 2020)|MacBookAir9,1 328 | MacBook Pro 13-Inch "Core 2 Duo" 2.26 (SD/FW)|MacBookPro5,5 329 | MacBook Pro 13-Inch "Core 2 Duo" 2.53 (SD/FW)|MacBookPro5,5 330 | MacBook Pro 13-Inch "Core 2 Duo" 2.4 Mid-2010|MacBookPro7,1 331 | MacBook Pro 13-Inch "Core 2 Duo" 2.66 Mid-2010|MacBookPro7,1 332 | MacBook Pro 13-Inch "Core i5" 2.3 Early 2011|MacBookPro8,1 333 | MacBook Pro 13-Inch "Core i7" 2.7 Early 2011|MacBookPro8,1 334 | MacBook Pro 13-Inch "Core i5" 2.4 Late 2011|MacBookPro8,1 335 | MacBook Pro 13-Inch "Core i7" 2.8 Late 2011|MacBookPro8,1 336 | MacBook Pro 13-Inch "Core i5" 2.5 Mid-2012|MacBookPro9,2 337 | MacBook Pro 13-Inch "Core i7" 2.9 Mid-2012|MacBookPro9,2 338 | MacBook Pro 13-Inch "Core i5" 2.5 Retina 2012|MacBookPro10,2 339 | MacBook Pro 13-Inch "Core i7" 2.9 Retina 2012|MacBookPro10,2 340 | MacBook Pro 13-Inch "Core i5" 2.6 Early 2013|MacBookPro10,2 341 | MacBook Pro 13-Inch "Core i7" 3.0 Early 2013|MacBookPro10,2 342 | MacBook Pro 13-Inch "Core i5" 2.4 Late 2013|MacBookPro11,1 343 | MacBook Pro 13-Inch "Core i5" 2.6 Late 2013|MacBookPro11,1 344 | MacBook Pro 13-Inch "Core i7" 2.8 Late 2013|MacBookPro11,1 345 | MacBook Pro 13-Inch "Core i5" 2.6 Mid-2014|MacBookPro11,1 346 | MacBook Pro 13-Inch "Core i5" 2.8 Mid-2014|MacBookPro11,1 347 | MacBook Pro 13-Inch "Core i7" 3.0 Mid-2014|MacBookPro11,1 348 | MacBook Pro 13-Inch "Core i5" 2.7 Early 2015|MacBookPro12,1 349 | MacBook Pro 13-Inch "Core i5" 2.9 Early 2015|MacBookPro12,1 350 | MacBook Pro 13-Inch "Core i7" 3.1 Early 2015|MacBookPro12,1 351 | MacBook Pro 13-Inch "Core i5" 2.0 Late 2016|MacBookPro13,1 352 | MacBook Pro 13-Inch "Core i7" 2.4 Late 2016|MacBookPro13,1 353 | MacBook Pro 13-Inch "Core i5" 2.9 Touch/Late 2016|MacBookPro13,2 354 | MacBook Pro 13-Inch "Core i5" 3.1 Touch/Late 2016|MacBookPro13,2 355 | MacBook Pro 13-Inch "Core i7" 3.3 Touch/Late 2016|MacBookPro13,2 356 | MacBook Pro 13-Inch "Core i5" 2.3 Mid-2017|MacBookPro14,1 357 | MacBook Pro 13-Inch "Core i7" 2.5 Mid-2017|MacBookPro14,1 358 | MacBook Pro 13-Inch "Core i5" 3.1 Touch/Mid-2017|MacBookPro14,2 359 | MacBook Pro 13-Inch "Core i5" 3.3 Touch/Mid-2017|MacBookPro14,2 360 | MacBook Pro 13-Inch "Core i7" 3.5 Touch/Mid-2017|MacBookPro14,2 361 | MacBook Pro 13-Inch "Core i5" 2.3 Touch/2018|MacBookPro15,2 362 | MacBook Pro 13-Inch "Core i7" 2.7 Touch/2018|MacBookPro15,2 363 | MacBook Pro 13-Inch "Core i5" 2.4 Touch/2019|MacBookPro15,2 364 | MacBook Pro 13-Inch "Core i7" 2.8 Touch/2019|MacBookPro15,2 365 | MacBook Pro 13-Inch "Core i5" 1.4 Touch/2019 2 TB 3|MacBookPro15,4 366 | MacBook Pro 13-Inch "Core i7" 1.7 Touch/2019 2 TB 3|MacBookPro15,4 367 | MacBook Pro 13-Inch "Core i5" 1.4 2020 2 TB 3 (Scissor)|MacBookPro16,3 368 | MacBook Pro 13-Inch "Core i7" 1.7 2020 2 TB 3 (Scissor)|MacBookPro16,3 369 | MacBook Pro 13-Inch "Core i5" 2.0 2020 4 TB 3 (Scissor)|MacBookPro16,2 370 | MacBook Pro 13-Inch "Core i7" 2.3 2020 4 TB 3 (Scissor)|MacBookPro16,2 371 | MacBook Pro 15-Inch "Core Duo" 1.67|MacBookPro1,1 372 | MacBook Pro 15-Inch "Core Duo" 1.83|MacBookPro1,1 373 | MacBook Pro 15-Inch "Core Duo" 2.0|MacBookPro1,1 374 | MacBook Pro 15-Inch "Core Duo" 2.16|MacBookPro1,1 375 | MacBook Pro 15-Inch "Core 2 Duo" 2.16|MacBookPro2,2 376 | MacBook Pro 15-Inch "Core 2 Duo" 2.33|MacBookPro2,2 377 | MacBook Pro 15-Inch "Core 2 Duo" 2.2 (SR)|MacBookPro3,1 378 | MacBook Pro 15-Inch "Core 2 Duo" 2.4 (SR)|MacBookPro3,1 379 | MacBook Pro 15-Inch "Core 2 Duo" 2.6 (SR)|MacBookPro3,1 380 | MacBook Pro 15-Inch "Core 2 Duo" 2.4 (08)|MacBookPro4,1 381 | MacBook Pro 15-Inch "Core 2 Duo" 2.5 (08)|MacBookPro4,1 382 | MacBook Pro 15-Inch "Core 2 Duo" 2.6 (08)|MacBookPro4,1 383 | MacBook Pro 15-Inch "Core 2 Duo" 2.4 (Unibody)|MacBookPro5,1 384 | MacBook Pro 15-Inch "Core 2 Duo" 2.53 (Unibody)|MacBookPro5,1 385 | MacBook Pro 15-Inch "Core 2 Duo" 2.8 (Unibody)|MacBookPro5,1 386 | MacBook Pro 15-Inch "Core 2 Duo" 2.66 (Unibody)|MacBookPro5,1 387 | MacBook Pro 15-Inch "Core 2 Duo" 2.93 (Unibody)|MacBookPro5,1 388 | MacBook Pro 15-Inch "Core 2 Duo" 2.53 (SD)|MacBookPro5,4 389 | MacBook Pro 15-Inch "Core 2 Duo" 2.66 (SD)|MacBookPro5,3 390 | MacBook Pro 15-Inch "Core 2 Duo" 2.8 (SD)|MacBookPro5,3 391 | MacBook Pro 15-Inch "Core 2 Duo" 3.06 (SD)|MacBookPro5,3 392 | MacBook Pro 15-Inch "Core i5" 2.4 Mid-2010|MacBookPro6,2 393 | MacBook Pro 15-Inch "Core i5" 2.53 Mid-2010|MacBookPro6,2 394 | MacBook Pro 15-Inch "Core i7" 2.66 Mid-2010|MacBookPro6,2 395 | MacBook Pro 15-Inch "Core i7" 2.8 Mid-2010|MacBookPro6,2 396 | MacBook Pro 15-Inch "Core i7" 2.0 Early 2011|MacBookPro8,2 397 | MacBook Pro 15-Inch "Core i7" 2.2 Early 2011|MacBookPro8,2 398 | MacBook Pro 15-Inch "Core i7" 2.3 Early 2011|MacBookPro8,2 399 | MacBook Pro 15-Inch "Core i7" 2.2 Late 2011|MacBookPro8,2 400 | MacBook Pro 15-Inch "Core i7" 2.4 Late 2011|MacBookPro8,2 401 | MacBook Pro 15-Inch "Core i7" 2.5 Late 2011|MacBookPro8,2 402 | MacBook Pro 15-Inch "Core i7" 2.3 Mid-2012|MacBookPro9,1 403 | MacBook Pro 15-Inch "Core i7" 2.6 Mid-2012|MacBookPro9,1 404 | MacBook Pro 15-Inch "Core i7" 2.7 Mid-2012|MacBookPro9,1 405 | MacBook Pro 15-Inch "Core i7" 2.3 Retina 2012|MacBookPro10,1 406 | MacBook Pro 15-Inch "Core i7" 2.6 Retina 2012|MacBookPro10,1 407 | MacBook Pro 15-Inch "Core i7" 2.7 Retina 2012|MacBookPro10,1 408 | MacBook Pro 15-Inch "Core i7" 2.4 Early 2013|MacBookPro10,1 409 | MacBook Pro 15-Inch "Core i7" 2.7 Early 2013|MacBookPro10,1 410 | MacBook Pro 15-Inch "Core i7" 2.8 Early 2013|MacBookPro10,1 411 | MacBook Pro 15-Inch "Core i7" 2.0 Late 2013 (IG)|MacBookPro11,2 412 | MacBook Pro 15-Inch "Core i7" 2.3 Late 2013 (IG)|MacBookPro11,2 413 | MacBook Pro 15-Inch "Core i7" 2.6 Late 2013 (IG)|MacBookPro11,2 414 | MacBook Pro 15-Inch "Core i7" 2.3 Late 2013 (DG)|MacBookPro11,3 415 | MacBook Pro 15-Inch "Core i7" 2.6 Late 2013 (DG)|MacBookPro11,3 416 | MacBook Pro 15-Inch "Core i7" 2.2 Mid-2014 (IG)|MacBookPro11,2 417 | MacBook Pro 15-Inch "Core i7" 2.5 Mid-2014 (IG)|MacBookPro11,2 418 | MacBook Pro 15-Inch "Core i7" 2.8 Mid-2014 (IG)|MacBookPro11,2 419 | MacBook Pro 15-Inch "Core i7" 2.5 Mid-2014 (DG)|MacBookPro11,3 420 | MacBook Pro 15-Inch "Core i7" 2.8 Mid-2014 (DG)|MacBookPro11,3 421 | MacBook Pro 15-Inch "Core i7" 2.2 Mid-2015 (IG)|MacBookPro11,4 422 | MacBook Pro 15-Inch "Core i7" 2.5 Mid-2015 (IG)|MacBookPro11,4 423 | MacBook Pro 15-Inch "Core i7" 2.8 Mid-2015 (IG)|MacBookPro11,4 424 | MacBook Pro 15-Inch "Core i7" 2.5 Mid-2015 (DG)|MacBookPro11,5 425 | MacBook Pro 15-Inch "Core i7" 2.8 Mid-2015 (DG)|MacBookPro11,5 426 | MacBook Pro 15-Inch "Core i7" 2.6 Touch/Late 2016|MacBookPro13,3 427 | MacBook Pro 15-Inch "Core i7" 2.7 Touch/Late 2016|MacBookPro13,3 428 | MacBook Pro 15-Inch "Core i7" 2.9 Touch/Late 2016|MacBookPro13,3 429 | MacBook Pro 15-Inch "Core i7" 2.8 Touch/Mid-2017|MacBookPro14,3 430 | MacBook Pro 15-Inch "Core i7" 2.9 Touch/Mid-2017|MacBookPro14,3 431 | MacBook Pro 15-Inch "Core i7" 3.1 Touch/Mid-2017|MacBookPro14,3 432 | MacBook Pro 15-Inch "Core i7" 2.2 Touch/2018|MacBookPro15,1 433 | MacBook Pro 15-Inch "Core i7" 2.6 Touch/2018|MacBookPro15,1 434 | MacBook Pro 15-Inch "Core i7" 2.6 Touch/2018 Vega|MacBookPro15,3 435 | MacBook Pro 15-Inch "Core i9" 2.9 Touch/2018|MacBookPro15,1 436 | MacBook Pro 15-Inch "Core i9" 2.9 Touch/2018 Vega|MacBookPro15,3 437 | MacBook Pro 15-Inch "Core i7" 2.6 Touch/2019|MacBookPro15,1 438 | MacBook Pro 15-Inch "Core i9" 2.3 Touch/2019|MacBookPro15,1 439 | MacBook Pro 15-Inch "Core i9" 2.3 Touch/2019 Vega|MacBookPro15,3 440 | MacBook Pro 15-Inch "Core i9" 2.4 Touch/2019|MacBookPro15,1 441 | MacBook Pro 15-Inch "Core i9" 2.4 Touch/2019 Vega|MacBookPro15,3 442 | MacBook Pro 16-Inch "Core i7" 2.6 2019 (Scissor)|MacBookPro16,1 443 | MacBook Pro 16-Inch "Core i9" 2.3 2019 (Scissor)|MacBookPro16,1 444 | MacBook Pro 16-Inch "Core i9" 2.4 2019 (Scissor)|MacBookPro16,1 445 | MacBook Pro 17-Inch "Core Duo" 2.16|MacBookPro1,2 446 | MacBook Pro 17-Inch "Core 2 Duo" 2.33|MacBookPro2,1 447 | MacBook Pro 17-Inch "Core 2 Duo" 2.4 (SR)|MacBookPro3,1 448 | MacBook Pro 17-Inch "Core 2 Duo" 2.6 (SR)|MacBookPro3,1 449 | MacBook Pro 17-Inch "Core 2 Duo" 2.5 (08)|MacBookPro4,1 450 | MacBook Pro 17-Inch "Core 2 Duo" 2.6 (08)|MacBookPro4,1 451 | MacBook Pro 17-Inch "Core 2 Duo" 2.66 (Unibody)|MacBookPro5,2 452 | MacBook Pro 17-Inch "Core 2 Duo" 2.93 (Unibody)|MacBookPro5,2 453 | MacBook Pro 17-Inch "Core 2 Duo" 2.8 Mid-2009|MacBookPro5,2 454 | MacBook Pro 17-Inch "Core 2 Duo" 3.06 Mid-2009|MacBookPro5,2 455 | MacBook Pro 17-Inch "Core i5" 2.53 Mid-2010|MacBookPro6,1 456 | MacBook Pro 17-Inch "Core i7" 2.66 Mid-2010|MacBookPro6,1 457 | MacBook Pro 17-Inch "Core i7" 2.8 Mid-2010|MacBookPro6,1 458 | MacBook Pro 17-Inch "Core i7" 2.2 Early 2011|MacBookPro8,3 459 | MacBook Pro 17-Inch "Core i7" 2.3 Early 2011|MacBookPro8,3 460 | MacBook Pro 17-Inch "Core i7" 2.4 Late 2011|MacBookPro8,3 461 | MacBook Pro 17-Inch "Core i7" 2.5 Late 2011|MacBookPro8,3 462 | Power Macintosh G3 233 Desktop|N/A* 463 | Power Macintosh G3 233 Minitower|N/A* 464 | Power Macintosh G3 266 Desktop|N/A* 465 | Power Macintosh G3 266 Minitower|N/A* 466 | Power Macintosh G3 300 Desktop|N/A* 467 | Power Macintosh G3 300 Minitower|N/A* 468 | Power Macintosh G3 333 Minitower|N/A* 469 | Power Macintosh G3 233 All-in-One|N/A* 470 | Power Macintosh G3 266 All-in-One|N/A* 471 | Power Macintosh G3 300 (Blue & White)|PowerMac1,1 472 | Power Macintosh G3 350 (Blue & White)|PowerMac1,1 473 | Power Macintosh G3 400 (Blue & White)|PowerMac1,1 474 | Power Macintosh G3 450 (Blue & White)|PowerMac1,1 475 | Power Macintosh G4 400 (PCI)|PowerMac1,2 476 | Power Macintosh G4 450 (AGP)|PowerMac3,1 477 | Power Macintosh G4 500 (AGP)|PowerMac3,1 478 | Power Macintosh G4 350 (PCI)|PowerMac1,2 479 | Power Macintosh G4 400 (AGP)|PowerMac3,1 480 | Power Macintosh G4 350 (AGP)|PowerMac3,1 481 | Power Macintosh G4 400 (Gigabit)|PowerMac3,3 482 | Power Macintosh G4 450 DP (Gigabit)|PowerMac3,3 483 | Power Macintosh G4 500 DP (Gigabit)|PowerMac3,3 484 | Power Macintosh G4 450 Cube|PowerMac5,1 485 | Power Macintosh G4 500 Cube|PowerMac5,1 486 | Power Macintosh G4 466 (Digital Audio)|PowerMac3,4 487 | Power Macintosh G4 533 (Digital Audio)|PowerMac3,4 488 | Power Macintosh G4 667 (Digital Audio)|PowerMac3,4 489 | Power Macintosh G4 733 (Digital Audio)|PowerMac3,4 490 | Power Macintosh G4 733 (Quicksilver)|PowerMac3,5 491 | Power Macintosh G4 867 (Quicksilver)|PowerMac3,5 492 | Power Macintosh G4 800 DP (Quicksilver)|PowerMac3,5 493 | Power Macintosh G4 800 (QS 2002)|PowerMac3,5 494 | Power Macintosh G4 933 (QS 2002)|PowerMac3,5 495 | Power Macintosh G4 1.0 DP (QS 2002)|PowerMac3,5 496 | Power Macintosh G4 867 DP (MDD)|PowerMac3,6 497 | Power Macintosh G4 1.0 DP (MDD)|PowerMac3,6 498 | Power Macintosh G4 1.25 DP (MDD)|PowerMac3,6 499 | Power Macintosh G4 1.0 (FW 800)|PowerMac3,6 500 | Power Macintosh G4 1.25 DP (FW 800)|PowerMac3,6 501 | Power Macintosh G4 1.42 DP (FW 800)|PowerMac3,6 502 | Power Macintosh G4 1.25 (MDD 2003)|PowerMac3,6 503 | Power Macintosh G5 1.6 (PCI)|PowerMac7,2 504 | Power Macintosh G5 1.8 (PCI-X)|PowerMac7,2 505 | Power Macintosh G5 2.0 DP (PCI-X)|PowerMac7,2 506 | Power Macintosh G5 1.8 DP (PCI-X)|PowerMac7,2 507 | Power Macintosh G5 1.8 DP (PCI)|PowerMac7,3 508 | Power Macintosh G5 2.0 DP (PCI-X 2)|PowerMac7,3 509 | Power Macintosh G5 2.5 DP (PCI-X)|PowerMac7,3 510 | Power Macintosh G5 1.8 (PCI)|PowerMac9,1 511 | Power Macintosh G5 2.0 DP (PCI)|PowerMac7,3 512 | Power Macintosh G5 2.3 DP (PCI-X)|PowerMac7,3 513 | Power Macintosh G5 2.7 DP (PCI-X)|PowerMac7,3 514 | Power Macintosh G5 Dual Core (2.0)|PowerMac11,2 515 | Power Macintosh G5 Dual Core (2.3)|PowerMac11,2 516 | Power Macintosh G5 "Quad Core" (2.5)|PowerMac11,2 517 | PowerBook G3 250 (Original/Kanga/3500)|N/A* 518 | PowerBook G3 233 (Wallstreet)|N/A* 519 | PowerBook G3 250 (Wallstreet)|N/A* 520 | PowerBook G3 292 (Wallstreet)|N/A* 521 | PowerBook G3 233 (PDQ - Late 1998)|N/A* 522 | PowerBook G3 266 (PDQ - Late 1998)|N/A* 523 | PowerBook G3 300 (PDQ - Late 1998)|N/A* 524 | PowerBook G3 333 (Bronze KB/Lombard)|PowerBook1,1 525 | PowerBook G3 400 (Bronze KB/Lombard)|PowerBook1,1 526 | PowerBook G3 400 (Firewire/Pismo)|PowerBook3,1 527 | PowerBook G3 500 (Firewire/Pismo)|PowerBook3,1 528 | PowerBook G4 400 (Original - Ti)|PowerBook3,2 529 | PowerBook G4 500 (Original - Ti)|PowerBook3,2 530 | PowerBook G4 550 (Gigabit - Ti)|PowerBook3,3 531 | PowerBook G4 667 (Gigabit - Ti)|PowerBook3,3 532 | PowerBook G4 667 (DVI - Ti)|PowerBook3,4 533 | PowerBook G4 800 (DVI - Ti)|PowerBook3,4 534 | PowerBook G4 867 (Ti)|PowerBook3,5 535 | PowerBook G4 1.0 (Ti)|PowerBook3,5 536 | PowerBook G4 867 12" (Al)|PowerBook6,1 537 | PowerBook G4 1.0 17" (Al)|PowerBook5,1 538 | PowerBook G4 1.0 12" (DVI - Al)|PowerBook6,2 539 | PowerBook G4 1.0 15" (FW800 - Al)|PowerBook5,2 540 | PowerBook G4 1.25 15" (FW800 - Al)|PowerBook5,2 541 | PowerBook G4 1.33 17" (Al)|PowerBook5,3 542 | PowerBook G4 1.33 12" (Al)|PowerBook6,4 543 | PowerBook G4 1.33 15" (Al)|PowerBook5,4 544 | PowerBook G4 1.5 15" (Al)|PowerBook5,4 545 | PowerBook G4 1.5 17" (Al)|PowerBook5,5 546 | PowerBook G4 1.5 12" (Al)|PowerBook6,8 547 | PowerBook G4 1.5 15" (SMS/BT2 - Al)|PowerBook5,6 548 | PowerBook G4 1.67 15" (Al)|PowerBook5,6 549 | PowerBook G4 1.67 17" (Al)|PowerBook5,7 550 | PowerBook G4 1.67 15" (DLSD/HR - Al)|PowerBook5,8 551 | PowerBook G4 1.67 17" (DLSD/HR - Al)|PowerBook5,9 552 | Xserve G4/1.0|RackMac1,1 553 | Xserve G4/1.0 DP|RackMac1,1 554 | Xserve G4/1.33 (Slot Load)|RackMac1,2 555 | Xserve G4/1.33 DP (Slot Load)|RackMac1,2 556 | Xserve G4/1.33 DP Cluster Node|RackMac1,2 557 | Xserve G5/2.0 (PCI-X)|RackMac3,1 558 | Xserve G5/2.0 DP (PCI-X)|RackMac3,1 559 | Xserve G5/2.0 DP Cluster Node (PCI-X)|RackMac3,1 560 | Xserve G5/2.3 DP (PCI-X)|RackMac3,1 561 | Xserve G5/2.3 DP Cluster Node (PCI-X)|RackMac3,1 562 | Xserve Xeon 2.0 "Quad Core" (Late 2006)|Xserve1,1 563 | Xserve Xeon 2.66 "Quad Core" (Late 2006)|Xserve1,1 564 | Xserve Xeon 3.0 "Quad Core" (Late 2006)|Xserve1,1 565 | Xserve Xeon 2.8 "Quad Core" (Early 2008)|Xserve2,1 566 | Xserve Xeon 2.8 "Eight Core" (Early 2008)|Xserve2,1 567 | Xserve Xeon 3.0 "Eight Core" (Early 2008)|Xserve2,1 568 | Xserve Xeon Nehalem 2.26 "Quad Core"|Xserve3,1 569 | Xserve Xeon Nehalem 2.26 "Eight Core"|Xserve3,1 570 | Xserve Xeon Nehalem 2.66 "Eight Core"|Xserve3,1 571 | Xserve Xeon Nehalem 2.93 "Eight Core"|Xserve3,1 572 | -------------------------------------------------------------------------------- /Example/Shared/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 | -------------------------------------------------------------------------------- /Example/Shared/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 | "idiom" : "mac", 95 | "scale" : "1x", 96 | "size" : "16x16" 97 | }, 98 | { 99 | "idiom" : "mac", 100 | "scale" : "2x", 101 | "size" : "16x16" 102 | }, 103 | { 104 | "idiom" : "mac", 105 | "scale" : "1x", 106 | "size" : "32x32" 107 | }, 108 | { 109 | "idiom" : "mac", 110 | "scale" : "2x", 111 | "size" : "32x32" 112 | }, 113 | { 114 | "idiom" : "mac", 115 | "scale" : "1x", 116 | "size" : "128x128" 117 | }, 118 | { 119 | "idiom" : "mac", 120 | "scale" : "2x", 121 | "size" : "128x128" 122 | }, 123 | { 124 | "idiom" : "mac", 125 | "scale" : "1x", 126 | "size" : "256x256" 127 | }, 128 | { 129 | "idiom" : "mac", 130 | "scale" : "2x", 131 | "size" : "256x256" 132 | }, 133 | { 134 | "idiom" : "mac", 135 | "scale" : "1x", 136 | "size" : "512x512" 137 | }, 138 | { 139 | "idiom" : "mac", 140 | "scale" : "2x", 141 | "size" : "512x512" 142 | } 143 | ], 144 | "info" : { 145 | "author" : "xcode", 146 | "version" : 1 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Example/Shared/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Shared/BrowserState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BrowserState.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 5/19/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | class BrowserState: ObservableObject { 11 | @Published var resolvedServiceProviders = Set() 12 | 13 | var resolvedServiceSections: [String?] { 14 | Set(resolvedServiceProviders.compactMap({ $0.txtRecord?["ServerName"] })) 15 | .sorted(by: { $0.localizedCompare($1) == .orderedAscending }) + [nil] 16 | } 17 | 18 | func resolvedServiceProvidersInSection(_ section: String?) -> [ServiceState] { 19 | resolvedServiceProviders 20 | .filter({ $0.txtRecord?["ServerName"] == section }) 21 | .sorted(by: { $0.name.localizedCompare($1.name) == .orderedAscending }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Example/Shared/BrowserView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BrowserView.swift 3 | // Shared 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BrowserView: View { 11 | 12 | @ObservedObject var state: BrowserState 13 | 14 | #if os(macOS) 15 | let columns = [ 16 | GridItem(.flexible()), 17 | GridItem(.flexible()), 18 | GridItem(.flexible()), 19 | GridItem(.flexible()), 20 | GridItem(.flexible()), 21 | GridItem(.flexible()), 22 | ] 23 | #else 24 | let columns = [ 25 | GridItem(.flexible()), 26 | GridItem(.flexible()), 27 | GridItem(.flexible()), 28 | ] 29 | #endif 30 | 31 | func formSection(_ section: String?) -> some View { 32 | Section( 33 | header: Text(section ?? "Others") 34 | .font(.system(.headline)) 35 | .textCase(.none) 36 | .padding() 37 | ) { 38 | LazyVGrid(columns: columns) { 39 | ForEach( 40 | state.resolvedServiceProvidersInSection(section), 41 | id: \.self 42 | ) { service in 43 | DeviceView(serviceState: service) 44 | } 45 | } 46 | } 47 | } 48 | 49 | var form: some View { 50 | Form { 51 | ForEach( 52 | state.resolvedServiceSections, 53 | id: \.self 54 | ) { section in 55 | formSection(section) 56 | } 57 | } 58 | } 59 | 60 | var list: some View { 61 | #if os(macOS) 62 | ScrollView { 63 | form 64 | } 65 | .background(Color.white) 66 | #else 67 | NavigationView { 68 | form 69 | .background(Color.white) 70 | .navigationBarTitle(Text("SwiftBonjour"), displayMode: .inline) 71 | } 72 | #endif 73 | } 74 | 75 | var body: some View { 76 | #if os(macOS) 77 | list 78 | .frame(minWidth: 720, minHeight: 480) 79 | #else 80 | list 81 | #endif 82 | } 83 | } 84 | 85 | struct BrowserView_Previews: PreviewProvider { 86 | static var previews: some View { 87 | BrowserView(state: BrowserState()) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Example/Shared/DeviceView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeviceView.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import SwiftUI 9 | import MarkdownUI 10 | import Network 11 | 12 | struct DeviceView: View { 13 | 14 | @State private var showPopup: Bool = false 15 | 16 | var serviceState: ServiceState 17 | 18 | var body: some View { 19 | VStack { 20 | Image(systemName: HostClassType 21 | .displayTypeForHardwareModel( 22 | serviceState.txtRecord?["HWModel"] ?? "" 23 | ) 24 | .symbolName 25 | ) 26 | .resizable() 27 | .aspectRatio(contentMode: .fit) 28 | .frame(width: 32, height: 32, alignment: .center) 29 | 30 | Text( 31 | serviceState.txtRecord?["HostName"] ?? serviceState.name 32 | ) 33 | .font(.system(.caption)) 34 | .multilineTextAlignment(.center) 35 | .lineLimit(2) 36 | } 37 | .padding() 38 | .onTapGesture { 39 | self.showPopup = true 40 | } 41 | .popover(isPresented: $showPopup, content: { 42 | ScrollView(showsIndicators: false) { 43 | Markdown(""" 44 | ### \(serviceState.hostName ?? "Unknown") 45 | 46 | #### Addresses 47 | 48 | \(serviceState.netService?.ipAddresses.compactMap({ String(describing: $0) }).joined(separator: "\n") ?? "") 49 | 50 | #### TXT Records 51 | 52 | ``` 53 | \(serviceState.txtRecord?.compactMap({ "Key: \($0.key)\nValue: \($0.value)" }).joined(separator: "\n\n") ?? "") 54 | ``` 55 | """ 56 | ) 57 | .padding() 58 | } 59 | .frame(minWidth: 240, minHeight: 160) 60 | }) 61 | } 62 | } 63 | 64 | struct DeviceView_Previews: PreviewProvider { 65 | static var previews: some View { 66 | DeviceView(serviceState: ServiceState()) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Example/Shared/HardwareModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HardwareModel.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 5/19/21. 6 | // 7 | 8 | #if os(macOS) 9 | import Foundation 10 | typealias HostClassType = Host 11 | #else 12 | import UIKit 13 | typealias HostClassType = UIDevice 14 | #endif 15 | 16 | enum DeviceType { 17 | case unknown 18 | case ipodtouch 19 | case iphoneLegacy 20 | case iphone 21 | case ipadLegacy 22 | case ipad 23 | case appletv 24 | case applewatch 25 | case homepod 26 | case macbook 27 | case macmini 28 | case imac 29 | case macproGen1 30 | case macproGen2 31 | case macproGen3 32 | case macproGen3Server 33 | 34 | var symbolName: String { 35 | switch self { 36 | case .unknown: 37 | return "bonjour" 38 | case .ipodtouch: 39 | return "ipodtouch" 40 | case .iphone: 41 | return "iphone" 42 | case .iphoneLegacy: 43 | return "iphone.homebutton" 44 | case .ipad: 45 | return "ipad" 46 | case .ipadLegacy: 47 | return "ipad.homebutton" 48 | case .appletv: 49 | return "appletv" 50 | case .applewatch: 51 | return "applewatch" 52 | case .homepod: 53 | return "homepod" 54 | case .macbook: 55 | return "laptopcomputer" 56 | case .macmini: 57 | return "macmini" 58 | case .imac: 59 | return "desktopcomputer" 60 | case .macproGen1: 61 | return "macpro.gen1" 62 | case .macproGen2: 63 | return "macpro.gen2" 64 | case .macproGen3: 65 | return "macpro.gen3" 66 | case .macproGen3Server: 67 | return "macpro.gen3.server" 68 | } 69 | } 70 | } 71 | 72 | extension HostClassType { 73 | static let hardwareModel: String = { 74 | #if os(macOS) 75 | let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")) 76 | defer { IOObjectRelease(service) } 77 | 78 | guard let modelData = IORegistryEntryCreateCFProperty(service, "model" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? Data else { 79 | fatalError("IORegistryEntryCreateCFProperty") 80 | } 81 | return modelData.withUnsafeBytes { String(cString: ($0.baseAddress?.assumingMemoryBound(to: UInt8.self))!) } 82 | #else 83 | var systemInfo = utsname() 84 | uname(&systemInfo) 85 | let machineMirror = Mirror(reflecting: systemInfo.machine) 86 | let identifier = machineMirror.children.reduce("") { identifier, element in 87 | guard let value = element.value as? Int8, value != 0 else { return identifier } 88 | return identifier + String(UnicodeScalar(UInt8(value))) 89 | } 90 | return identifier 91 | #endif 92 | }() 93 | 94 | static func displayTypeForHardwareModel(_ identifier: String) -> DeviceType { // swiftlint:disable:this cyclomatic_complexity 95 | if identifier.hasPrefix("iMac") { 96 | return .imac 97 | } 98 | else if identifier.hasPrefix("Macmini") { 99 | return .macmini 100 | } 101 | else if identifier.hasPrefix("MacBook") { 102 | return .macbook 103 | } 104 | else if identifier.hasPrefix("MacPro1") || identifier.hasPrefix("MacPro2") || identifier.hasPrefix("MacPro3") || identifier.hasPrefix("MacPro4") { 105 | return .macproGen1 106 | } 107 | else if identifier.hasPrefix("MacPro5") || identifier.hasPrefix("MacPro6") { 108 | return .macproGen2 109 | } 110 | else if identifier.hasPrefix("MacPro7") { 111 | return .macproGen3 112 | } 113 | switch identifier { 114 | case "iPod5,1": return .ipodtouch 115 | case "iPod7,1": return .ipodtouch 116 | case "iPod9,1": return .ipodtouch 117 | case "iPhone3,1", "iPhone3,2", "iPhone3,3": return .iphoneLegacy 118 | case "iPhone4,1": return .iphoneLegacy 119 | case "iPhone5,1", "iPhone5,2": return .iphoneLegacy 120 | case "iPhone5,3", "iPhone5,4": return .iphoneLegacy 121 | case "iPhone6,1", "iPhone6,2": return .iphoneLegacy 122 | case "iPhone7,2": return .iphoneLegacy 123 | case "iPhone7,1": return .iphoneLegacy 124 | case "iPhone8,1": return .iphoneLegacy 125 | case "iPhone8,2": return .iphoneLegacy 126 | case "iPhone8,4": return .iphoneLegacy 127 | case "iPhone9,1", "iPhone9,3": return .iphoneLegacy 128 | case "iPhone9,2", "iPhone9,4": return .iphoneLegacy 129 | case "iPhone10,1", "iPhone10,4": return .iphoneLegacy 130 | case "iPhone10,2", "iPhone10,5": return .iphoneLegacy 131 | case "iPhone10,3", "iPhone10,6": return .iphone 132 | case "iPhone11,2": return .iphone 133 | case "iPhone11,4", "iPhone11,6": return .iphone 134 | case "iPhone11,8": return .iphone 135 | case "iPhone12,1": return .iphone 136 | case "iPhone12,3": return .iphone 137 | case "iPhone12,5": return .iphone 138 | case "iPhone12,8": return .iphoneLegacy 139 | case "iPhone13,1": return .iphone 140 | case "iPhone13,2": return .iphone 141 | case "iPhone13,3": return .iphone 142 | case "iPhone13,4": return .iphone 143 | case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return .ipadLegacy 144 | case "iPad3,1", "iPad3,2", "iPad3,3": return .ipadLegacy 145 | case "iPad3,4", "iPad3,5", "iPad3,6": return .ipadLegacy 146 | case "iPad6,11", "iPad6,12": return .ipadLegacy 147 | case "iPad7,5", "iPad7,6": return .ipadLegacy 148 | case "iPad7,11", "iPad7,12": return .ipadLegacy 149 | case "iPad11,6", "iPad11,7": return .ipadLegacy 150 | case "iPad4,1", "iPad4,2", "iPad4,3": return .ipadLegacy 151 | case "iPad5,3", "iPad5,4": return .ipadLegacy 152 | case "iPad11,3", "iPad11,4": return .ipadLegacy 153 | case "iPad13,1", "iPad13,2": return .ipad 154 | case "iPad2,5", "iPad2,6", "iPad2,7": return .ipadLegacy 155 | case "iPad4,4", "iPad4,5", "iPad4,6": return .ipadLegacy 156 | case "iPad4,7", "iPad4,8", "iPad4,9": return .ipadLegacy 157 | case "iPad5,1", "iPad5,2": return .ipadLegacy 158 | case "iPad11,1", "iPad11,2": return .ipadLegacy 159 | case "iPad6,3", "iPad6,4": return .ipadLegacy 160 | case "iPad7,3", "iPad7,4": return .ipadLegacy 161 | case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return .ipad 162 | case "iPad8,9", "iPad8,10": return .ipad 163 | case "iPad6,7", "iPad6,8": return .ipad 164 | case "iPad7,1", "iPad7,2": return .ipad 165 | case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return .ipad 166 | case "iPad8,11", "iPad8,12": return .ipad 167 | case "AppleTV5,3": return .appletv 168 | case "AppleTV6,2": return .appletv 169 | case "AudioAccessory1,1": return .homepod 170 | case "AudioAccessory5,1": return .homepod 171 | case "i386", "x86_64": return .unknown 172 | default: return .unknown 173 | } 174 | } 175 | 176 | static let displayDeviceType: DeviceType = { 177 | return displayTypeForHardwareModel(hardwareModel) 178 | }() 179 | 180 | static func displayNameForHardwareModel(_ identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity 181 | switch identifier { 182 | case "iPod5,1": return "iPod touch (5th generation)" 183 | case "iPod7,1": return "iPod touch (6th generation)" 184 | case "iPod9,1": return "iPod touch (7th generation)" 185 | case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" 186 | case "iPhone4,1": return "iPhone 4s" 187 | case "iPhone5,1", "iPhone5,2": return "iPhone 5" 188 | case "iPhone5,3", "iPhone5,4": return "iPhone 5c" 189 | case "iPhone6,1", "iPhone6,2": return "iPhone 5s" 190 | case "iPhone7,2": return "iPhone 6" 191 | case "iPhone7,1": return "iPhone 6 Plus" 192 | case "iPhone8,1": return "iPhone 6s" 193 | case "iPhone8,2": return "iPhone 6s Plus" 194 | case "iPhone8,4": return "iPhone SE" 195 | case "iPhone9,1", "iPhone9,3": return "iPhone 7" 196 | case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus" 197 | case "iPhone10,1", "iPhone10,4": return "iPhone 8" 198 | case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus" 199 | case "iPhone10,3", "iPhone10,6": return "iPhone X" 200 | case "iPhone11,2": return "iPhone XS" 201 | case "iPhone11,4", "iPhone11,6": return "iPhone XS Max" 202 | case "iPhone11,8": return "iPhone XR" 203 | case "iPhone12,1": return "iPhone 11" 204 | case "iPhone12,3": return "iPhone 11 Pro" 205 | case "iPhone12,5": return "iPhone 11 Pro Max" 206 | case "iPhone12,8": return "iPhone SE (2nd generation)" 207 | case "iPhone13,1": return "iPhone 12 mini" 208 | case "iPhone13,2": return "iPhone 12" 209 | case "iPhone13,3": return "iPhone 12 Pro" 210 | case "iPhone13,4": return "iPhone 12 Pro Max" 211 | case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" 212 | case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)" 213 | case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)" 214 | case "iPad6,11", "iPad6,12": return "iPad (5th generation)" 215 | case "iPad7,5", "iPad7,6": return "iPad (6th generation)" 216 | case "iPad7,11", "iPad7,12": return "iPad (7th generation)" 217 | case "iPad11,6", "iPad11,7": return "iPad (8th generation)" 218 | case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" 219 | case "iPad5,3", "iPad5,4": return "iPad Air 2" 220 | case "iPad11,3", "iPad11,4": return "iPad Air (3rd generation)" 221 | case "iPad13,1", "iPad13,2": return "iPad Air (4th generation)" 222 | case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad mini" 223 | case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad mini 2" 224 | case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad mini 3" 225 | case "iPad5,1", "iPad5,2": return "iPad mini 4" 226 | case "iPad11,1", "iPad11,2": return "iPad mini (5th generation)" 227 | case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" 228 | case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" 229 | case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch) (1st generation)" 230 | case "iPad8,9", "iPad8,10": return "iPad Pro (11-inch) (2nd generation)" 231 | case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch) (1st generation)" 232 | case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" 233 | case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" 234 | case "iPad8,11", "iPad8,12": return "iPad Pro (12.9-inch) (4th generation)" 235 | case "AppleTV5,3": return "Apple TV" 236 | case "AppleTV6,2": return "Apple TV 4K" 237 | case "AudioAccessory1,1": return "HomePod" 238 | case "AudioAccessory5,1": return "HomePod mini" 239 | case "i386", "x86_64": return "Simulator \(displayNameForHardwareModel(ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))" 240 | default: return identifier 241 | } 242 | } 243 | 244 | static let displayHardwareModel: String = { 245 | return displayNameForHardwareModel(hardwareModel) 246 | }() 247 | } 248 | -------------------------------------------------------------------------------- /Example/Shared/ServiceState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceState.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 5/19/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | class ServiceState: ObservableObject, Hashable { 11 | static func == (lhs: ServiceState, rhs: ServiceState) -> Bool { 12 | return lhs.hostName == rhs.hostName && lhs.domain == rhs.domain && lhs.name == rhs.name && lhs.port == rhs.port 13 | } 14 | 15 | func hash(into hasher: inout Hasher) { 16 | hasher.combine(domain) 17 | hasher.combine(name) 18 | hasher.combine(hostName) 19 | hasher.combine(port) 20 | } 21 | 22 | @Published var domain: String = "" 23 | @Published var name: String = "" 24 | @Published var hostName: String? 25 | @Published var port: Int = 0 26 | @Published var txtRecord: [String: String]? 27 | private(set) weak var netService: NetService? 28 | 29 | init() {} 30 | 31 | init(domain: String, name: String, hostName: String?, port: Int, txtRecord: [String: String]?) { 32 | self.domain = domain 33 | self.name = name 34 | self.hostName = hostName 35 | self.port = port 36 | self.txtRecord = txtRecord 37 | } 38 | 39 | init(netService: NetService) { 40 | self.domain = netService.domain 41 | self.name = netService.name 42 | self.hostName = netService.hostName 43 | self.port = netService.port 44 | self.txtRecord = netService.txtRecordDictionary 45 | self.netService = netService 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Example/Shared/ServiceView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceView.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 5/19/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ServiceView: View { 11 | @ObservedObject var state: ServiceState 12 | 13 | var messageView: some View { 14 | if !state.domain.isEmpty { 15 | return Text("Service published at domain \(state.domain) port \(String(state.port))") 16 | } else { 17 | return Text("Will publish...") 18 | } 19 | } 20 | 21 | var body: some View { 22 | messageView 23 | .padding() 24 | .frame(minWidth: 200, minHeight: 120) 25 | } 26 | } 27 | 28 | struct ServiceView_Previews: PreviewProvider { 29 | static var previews: some View { 30 | ServiceView(state: ServiceState()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/Shared/SwiftBonjourApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftBonjourApp.swift 3 | // Shared 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftBonjour 10 | 11 | @main 12 | struct SwiftBonjourApp: App { 13 | 14 | static let serviceType = ServiceType.tcp("http") 15 | 16 | #if os(macOS) 17 | static let computerName = Host.current().localizedName ?? ProcessInfo().hostName 18 | static let willUpdateNotificationName = NSApplication.willUpdateNotification 19 | #else 20 | static let computerName = UIDevice.current.name 21 | static let didBecomeActiveNotificationName = UIApplication.didBecomeActiveNotification 22 | static let willResignActiveNotificationName = UIApplication.willResignActiveNotification 23 | #endif 24 | 25 | #if SERVICE 26 | let server = BonjourServer( 27 | type: SwiftBonjourApp.serviceType, 28 | name: "\(SwiftBonjourApp.computerName) (\(String(describing: SwiftBonjourApp.self)))" 29 | ) 30 | let state = ServiceState() 31 | #else 32 | let browser = BonjourBrowser() 33 | let state = BrowserState() 34 | #endif 35 | 36 | var innerView: some View { 37 | #if SERVICE 38 | ServiceView(state: state) 39 | #else 40 | BrowserView(state: state) 41 | #endif 42 | } 43 | 44 | var outerView: some View { 45 | innerView 46 | .onAppear { 47 | DispatchQueue.main.async { 48 | #if SERVICE 49 | 50 | server.txtRecord = [ 51 | "HWModel": HostClassType.hardwareModel, 52 | "HostName": SwiftBonjourApp.computerName, 53 | "ServerName": String(describing: SwiftBonjourApp.self), 54 | "ServerVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" 55 | ] 56 | 57 | server.start { succeed in 58 | print("Bonjour server started: ", succeed) 59 | state.domain = server.netService.domain 60 | state.port = server.netService.port 61 | state.txtRecord = server.txtRecord ?? [:] 62 | } 63 | 64 | #else 65 | 66 | browser.serviceFoundHandler = { service in 67 | print("Service found") 68 | print(service) 69 | } 70 | 71 | browser.serviceResolvedHandler = { result in 72 | print("Service resolved") 73 | print(result) 74 | switch result { 75 | case let .success(service): 76 | state.resolvedServiceProviders.insert(ServiceState(netService: service)) 77 | case .failure(_): 78 | break 79 | } 80 | } 81 | 82 | browser.serviceRemovedHandler = { service in 83 | print("Service removed") 84 | print(service) 85 | if let serviceToRemove = state.resolvedServiceProviders.first(where: { $0.domain == service.domain && $0.name == service.name }) { 86 | state.resolvedServiceProviders.remove(serviceToRemove) 87 | } 88 | } 89 | 90 | browser.browse(type: SwiftBonjourApp.serviceType) 91 | 92 | #endif 93 | } 94 | } 95 | .onDisappear { 96 | DispatchQueue.main.async { 97 | #if SERVICE 98 | server.stop() 99 | #else 100 | browser.stop() 101 | #endif 102 | } 103 | } 104 | } 105 | 106 | var body: some Scene { 107 | WindowGroup { 108 | #if os(macOS) 109 | outerView 110 | .onReceive(NotificationCenter.default.publisher(for: SwiftBonjourApp.willUpdateNotificationName), perform: { _ in 111 | hideZoomButton() 112 | }) 113 | #else 114 | outerView 115 | .onReceive(NotificationCenter.default.publisher(for: SwiftBonjourApp.didBecomeActiveNotificationName), perform: { _ in 116 | DispatchQueue.main.async { 117 | #if SERVICE 118 | server.start() 119 | #else 120 | browser.browse(type: SwiftBonjourApp.serviceType) 121 | #endif 122 | } 123 | }) 124 | .onReceive(NotificationCenter.default.publisher(for: SwiftBonjourApp.willResignActiveNotificationName), perform: { _ in 125 | DispatchQueue.main.async { 126 | #if SERVICE 127 | server.stop() 128 | #else 129 | browser.stop() 130 | #endif 131 | } 132 | }) 133 | #endif 134 | } 135 | } 136 | 137 | #if os(macOS) 138 | func hideZoomButton() { 139 | for window in NSApplication.shared.windows { 140 | window.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true 141 | window.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true 142 | window.level = .statusBar 143 | } 144 | } 145 | #endif 146 | } 147 | -------------------------------------------------------------------------------- /Example/SwiftBonjour/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 | 22 | 23 | -------------------------------------------------------------------------------- /Example/SwiftBonjour/SwiftBonjour.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftBonjour.h 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 5/20/21. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for SwiftBonjour. 11 | FOUNDATION_EXPORT double SwiftBonjourVersionNumber; 12 | 13 | //! Project version string for SwiftBonjour. 14 | FOUNDATION_EXPORT const unsigned char SwiftBonjourVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /Example/iOS/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 | NSBonjourServices 24 | 25 | _http._tcp. 26 | 27 | NSLocalNetworkUsageDescription 28 | $(PRODUCT_NAME) uses your local network to discover other devices. 29 | UIApplicationSceneManifest 30 | 31 | UIApplicationSupportsMultipleScenes 32 | 33 | 34 | UIApplicationSupportsIndirectInputEvents 35 | 36 | UILaunchScreen 37 | 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Example/macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/macOS/macOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.network.client 10 | 11 | com.apple.security.network.server 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 i_82 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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | #if os(Linux) 7 | let dependencies: [Package.Dependency] = [ 8 | .package(url: "https://github.com/Bouke/NetService.git", from: "0.8.1"), 9 | ] 10 | let dependencyNames: [Target.Dependency] = ["NetService"] 11 | #else 12 | let dependencies: [Package.Dependency] = [] 13 | let dependencyNames: [Target.Dependency] = [] 14 | #endif 15 | 16 | let package = Package( 17 | name: "SwiftBonjour", 18 | platforms: [.macOS(.v10_12), 19 | .iOS(.v10), 20 | .tvOS(.v10)], 21 | products: [ 22 | .library( 23 | name: "SwiftBonjour", 24 | targets: ["SwiftBonjour"]), 25 | ], 26 | dependencies: dependencies, 27 | targets: [ 28 | .target( 29 | name: "SwiftBonjour", 30 | dependencies: dependencyNames), 31 | ] 32 | ) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftBonjour 2 | 3 | Using NetService (*Bonjour*) to enable network discovery in your app. 4 | 5 | This is a maintained derivative fork of [Ciao](https://github.com/AlTavares/Ciao). 6 | 7 | 8 | ## What's Bonjour? 9 | 10 | Bonjour, also known as zero-configuration networking, enables automatic discovery of devices and services on a local network using industry standard IP protocols. Bonjour makes it easy to discover, publish, and resolve network services with a sophisticated, easy-to-use programming interface that is accessible from Cocoa, Ruby, Python, and other languages. [Bonjour - Apple Developer](https://developer.apple.com/bonjour/) 11 | 12 | 13 | ## Example 14 | 15 | ![Example 1](./Example/Screenshots/example_1.png) 16 | 17 | 18 | ## Real-World Demo 19 | 20 | ![Demo 1](./Example/Screenshots/demo_1.jpg) 21 | 22 | 23 | ## Usage 24 | 25 | ### Swift Package Manager 26 | 27 | To use SwiftBonjour as a [Swift Package Manager](https://swift.org/package-manager/) package just add the following in your Package.swift file. 28 | 29 | ``` swift 30 | dependencies: [ 31 | .package(url: "https://github.com/Lessica/SwiftBonjour.git") 32 | ] 33 | ``` 34 | 35 | 36 | ## Other Libraries 37 | 38 | - [GCDWebServer](https://github.com/swisspol/GCDWebServer) 39 | 40 | 41 | ## License 42 | 43 | SwiftBonjour is released under the MIT license. See [LICENSE](https://github.com/Lessica/SwiftBonjour/blob/main/LICENSE) for details. 44 | 45 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/BonjourBrowser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BonjourBrowser.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | #if os(Linux) 10 | import NetService 11 | #else 12 | import Network 13 | #endif 14 | 15 | public class BonjourBrowser { 16 | var netServiceBrowser: NetServiceBrowser 17 | var delegate: BonjourBrowserDelegate 18 | 19 | public var services = Set() 20 | 21 | // Handlers 22 | public var serviceFoundHandler: ((NetService) -> Void)? 23 | public var serviceRemovedHandler: ((NetService) -> Void)? 24 | public var serviceResolvedHandler: ((Result) -> Void)? 25 | 26 | 27 | public var isSearching = false { 28 | didSet { 29 | BonjourLogger.info(isSearching) 30 | } 31 | } 32 | 33 | private var isBrowsering = false 34 | 35 | public init() { 36 | netServiceBrowser = NetServiceBrowser() 37 | delegate = BonjourBrowserDelegate() 38 | netServiceBrowser.delegate = delegate 39 | delegate.browser = self 40 | } 41 | 42 | deinit { 43 | stop() 44 | } 45 | 46 | public func browse(type: ServiceType, domain: String = "") { 47 | browse(type: type.description, domain: domain) 48 | } 49 | 50 | public func browse(type: String, domain: String = "") { 51 | isBrowsering = true 52 | netServiceBrowser.searchForServices(ofType: type, inDomain: domain) 53 | } 54 | 55 | fileprivate func serviceFound(_ service: NetService) { 56 | services.update(with: service) 57 | serviceFoundHandler?(service) 58 | 59 | // resolve services if handler is registered 60 | guard let serviceResolvedHandler = serviceResolvedHandler else { return } 61 | var resolver: BonjourResolver? = BonjourResolver(service: service) 62 | resolver?.resolve(withTimeout: 0) { result in 63 | serviceResolvedHandler(result) 64 | // retain resolver until resolution 65 | resolver = nil 66 | } 67 | } 68 | 69 | fileprivate func serviceRemoved(_ service: NetService) { 70 | services.remove(service) 71 | serviceRemovedHandler?(service) 72 | } 73 | 74 | public func stop() { 75 | guard !isBrowsering else { return } 76 | netServiceBrowser.stop() 77 | } 78 | } 79 | 80 | class BonjourBrowserDelegate: NSObject, NetServiceBrowserDelegate { 81 | weak var browser: BonjourBrowser? 82 | func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) { 83 | BonjourLogger.info("Bonjour service found", service) 84 | self.browser?.serviceFound(service) 85 | } 86 | 87 | func netServiceBrowserWillSearch(_ browser: NetServiceBrowser) { 88 | BonjourLogger.info("Bonjour browser will search") 89 | self.browser?.isSearching = true 90 | } 91 | 92 | func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) { 93 | BonjourLogger.info("Bonjour browser stopped search") 94 | self.browser?.isSearching = false 95 | } 96 | 97 | func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String: NSNumber]) { 98 | BonjourLogger.debug("Bonjour browser did not search", errorDict) 99 | self.browser?.isSearching = false 100 | } 101 | 102 | func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) { 103 | BonjourLogger.info("Bonjour service removed", service) 104 | self.browser?.serviceRemoved(service) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/BonjourLogger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BonjourLogger.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | #if os(Linux) 10 | public struct OSLogType: RawRepresentable { 11 | public static let `default` = OSLogType(rawValue: 0) 12 | public static let debug = OSLogType(rawValue: -2) 13 | public static let info = OSLogType(rawValue: -1) 14 | public static let error = OSLogType(rawValue: 1) 15 | public static let fault = OSLogType(rawValue: 2) 16 | 17 | public typealias RawValue = Int 18 | 19 | public var rawValue: Int 20 | 21 | public init(rawValue: Int) { 22 | self.rawValue = rawValue 23 | } 24 | } 25 | #else 26 | import OSLog 27 | #endif 28 | 29 | public var LoggerLevel = OSLogType.default 30 | 31 | struct BonjourLogger { 32 | private static func log(_ message: [Any], 33 | level: OSLogType, 34 | fileName: String = #file, 35 | line: Int = #line, 36 | funcName: String = #function) { 37 | guard level.rawValue >= LoggerLevel.rawValue else { return } 38 | let msg = message.map { String(describing: $0) }.joined(separator: ", ") 39 | #if os(Linux) 40 | print("[\(sourceFileName(filePath: fileName))]:\(line) \(funcName) -> \(msg)") 41 | #else 42 | os_log("[%@]:%ld %@ -> %@", log: .default, type: level, sourceFileName(filePath: fileName), line, funcName, msg) 43 | #endif 44 | } 45 | 46 | private static func sourceFileName(filePath: String) -> String { 47 | let components = filePath.components(separatedBy: "/") 48 | return components.isEmpty ? "" : components.last! 49 | } 50 | } 51 | 52 | extension BonjourLogger { 53 | static func verbose(_ message: Any..., 54 | fileName: String = #file, 55 | line: Int = #line, 56 | funcName: String = #function) { 57 | BonjourLogger.log(message, level: .default, fileName: fileName, line: line, funcName: funcName) 58 | } 59 | 60 | static func debug(_ message: Any..., 61 | fileName: String = #file, 62 | line: Int = #line, 63 | funcName: String = #function) { 64 | BonjourLogger.log(message, level: .debug, fileName: fileName, line: line, funcName: funcName) 65 | } 66 | 67 | static func info(_ message: Any..., 68 | fileName: String = #file, 69 | line: Int = #line, 70 | funcName: String = #function) { 71 | BonjourLogger.log(message, level: .info, fileName: fileName, line: line, funcName: funcName) 72 | } 73 | 74 | static func error(_ message: Any..., 75 | fileName: String = #file, 76 | line: Int = #line, 77 | funcName: String = #function) { 78 | BonjourLogger.log(message, level: .error, fileName: fileName, line: line, funcName: funcName) 79 | } 80 | 81 | static func fault(_ message: Any..., 82 | fileName: String = #file, 83 | line: Int = #line, 84 | funcName: String = #function) { 85 | BonjourLogger.log(message, level: .fault, fileName: fileName, line: line, funcName: funcName) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/BonjourResolver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BonjourResolver.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | #if os(Linux) 10 | import NetService 11 | #else 12 | import Network 13 | #endif 14 | 15 | public class BonjourResolver { 16 | public init(service: NetService) { 17 | self.service = service 18 | } 19 | 20 | let service: NetService 21 | let delegate: BonjourResolverDelegate = BonjourResolverDelegate() 22 | 23 | public func resolve(withTimeout timeout: TimeInterval, completion: @escaping (Result) -> Void) { 24 | delegate.onResolve = completion 25 | service.delegate = delegate 26 | service.resolve(withTimeout: timeout) 27 | } 28 | 29 | deinit { 30 | BonjourLogger.verbose(self) 31 | service.stop() 32 | } 33 | 34 | } 35 | 36 | public typealias ErrorDictionary = [String: Int] 37 | extension ErrorDictionary: Error {} 38 | 39 | extension BonjourResolver { 40 | class BonjourResolverDelegate: NSObject, NetServiceDelegate { 41 | var onResolve: ((Result) -> Void)? 42 | 43 | func netService(_ sender: NetService, didNotResolve errorDict: [String: NSNumber]) { 44 | BonjourLogger.fault("Bonjour service did not resolve", sender, errorDict) 45 | let transformed = errorDict.mapValues { value in 46 | Int(truncating: value) 47 | } 48 | onResolve?(Result.failure(transformed)) 49 | } 50 | 51 | func netServiceDidResolveAddress(_ sender: NetService) { 52 | BonjourLogger.info("Bonjour service resolved", sender) 53 | onResolve?(Result.success(sender)) 54 | } 55 | 56 | func netServiceWillResolve(_ sender: NetService) { 57 | BonjourLogger.info("Bonjour service will resolve", sender) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/BonjourServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BonjourServer.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | #if os(Linux) 10 | import NetService 11 | #else 12 | import Network 13 | #endif 14 | 15 | public class BonjourServer { 16 | 17 | public private(set) var serviceType: ServiceType 18 | public private(set) var netService: NetService 19 | var delegate: BonjourServerDelegate? 20 | var successCallback: ((Bool) -> Void)? 21 | 22 | public fileprivate(set) var started = false { 23 | didSet { 24 | successCallback?(started) 25 | successCallback = nil 26 | } 27 | } 28 | 29 | public var txtRecord: [String: String]? { 30 | get { 31 | return netService.txtRecordDictionary 32 | } 33 | set { 34 | netService.setTXTRecord(dictionary: newValue) 35 | BonjourLogger.info("TXT Record updated", newValue as Any) 36 | } 37 | } 38 | 39 | public init(type: ServiceType, domain: String = "", name: String = "", port: Int32 = 0) { 40 | serviceType = type 41 | netService = NetService(domain: domain, type: type.description, name: name, port: port) 42 | delegate = BonjourServerDelegate() 43 | delegate?.server = self 44 | netService.delegate = delegate 45 | } 46 | 47 | public func start(options: NetService.Options = [.listenForConnections]) { 48 | start(options: options, success: successCallback) 49 | } 50 | 51 | public func start(options: NetService.Options = [.listenForConnections], success: ((Bool) -> Void)?) { 52 | if started { 53 | success?(true) 54 | return 55 | } 56 | successCallback = success 57 | netService.schedule(in: RunLoop.current, forMode: RunLoop.Mode.common) 58 | netService.publish(options: options) 59 | } 60 | 61 | public func stop() { 62 | netService.stop() 63 | } 64 | 65 | deinit { 66 | stop() 67 | netService.delegate = nil 68 | delegate = nil 69 | } 70 | } 71 | 72 | class BonjourServerDelegate: NSObject, NetServiceDelegate { 73 | weak var server: BonjourServer? 74 | 75 | func netServiceDidPublish(_ sender: NetService) { 76 | server?.started = true 77 | BonjourLogger.info("Bonjour server started at domain \(sender.domain) port \(sender.port)") 78 | } 79 | 80 | func netService(_ sender: NetService, didNotPublish errorDict: [String: NSNumber]) { 81 | server?.started = false 82 | BonjourLogger.fault("Bonjour server did not publish", errorDict) 83 | } 84 | 85 | func netServiceDidStop(_ sender: NetService) { 86 | server?.started = false 87 | BonjourLogger.info("Bonjour server stoped") 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/IPAddress+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IPAddress+Ext.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2023/12/29. 6 | // 7 | 8 | #if os(Linux) 9 | import Foundation 10 | 11 | // TODO: replace by sockaddr_storage 12 | 13 | /// Undefined for LE 14 | func htonl(_ value: UInt32) -> UInt32 { 15 | return value.byteSwapped 16 | } 17 | let ntohl = htonl 18 | 19 | public protocol IPAddress: CustomDebugStringConvertible { 20 | init?(_ networkBytes: Data) 21 | init?(_ presentation: String) 22 | var presentation: String { get } 23 | 24 | /// network-byte-order bytes 25 | var bytes: Data { get } 26 | } 27 | 28 | extension IPAddress { 29 | public var debugDescription: String { 30 | return presentation 31 | } 32 | } 33 | 34 | extension UInt32 { 35 | var bytes: Data { 36 | var value = self 37 | return Data(bytes: &value, count: MemoryLayout.size) 38 | } 39 | } 40 | 41 | // IPv4 address, wraps `in_addr`. This type is used to convert between 42 | // human-readable presentation format and bytes in both host order and 43 | // network order. 44 | public struct IPv4Address: IPAddress { 45 | /// IPv4 address in network-byte-order 46 | public let address: in_addr 47 | 48 | public init(address: in_addr) { 49 | self.address = address 50 | } 51 | 52 | public init?(_ presentation: String) { 53 | var address = in_addr() 54 | guard inet_pton(AF_INET, presentation, &address) == 1 else { 55 | return nil 56 | } 57 | self.address = address 58 | } 59 | 60 | /// network order 61 | public init?(_ networkBytes: Data) { 62 | guard networkBytes.count == MemoryLayout.size else { 63 | return nil 64 | } 65 | self.address = networkBytes.withUnsafeBytes({ (rawBufferPointer: UnsafeRawBufferPointer) -> in_addr in 66 | // Convert UnsafeRawBufferPointer to UnsafeBufferPointer 67 | let bufferPointer = rawBufferPointer.bindMemory(to: UInt8.self) 68 | // Convert UnsafeBufferPointer to UnsafePointer 69 | if let bytesPointer = bufferPointer.baseAddress?.withMemoryRebound(to: UInt8.self, capacity: networkBytes.count, { return $0 }) { 70 | return bytesPointer.withMemoryRebound(to: in_addr.self, capacity: 1) { $0.pointee } 71 | } 72 | return in_addr() 73 | }) 74 | } 75 | 76 | /// host order 77 | public init(_ address: UInt32) { 78 | self.address = in_addr(s_addr: htonl(address)) 79 | } 80 | 81 | /// Format this IPv4 address using common `a.b.c.d` notation. 82 | public var presentationString: String? { 83 | let length = Int(INET_ADDRSTRLEN) 84 | var presentationBytes = [CChar](repeating: 0, count: length) 85 | var addr = self.address 86 | guard inet_ntop(AF_INET, &addr, &presentationBytes, socklen_t(length)) != nil else { 87 | return nil 88 | } 89 | return String(cString: presentationBytes) 90 | } 91 | 92 | public var presentation: String { 93 | return presentationString ?? "Invalid IPv4 address" 94 | } 95 | 96 | public var bytes: Data { 97 | return htonl(address.s_addr).bytes 98 | } 99 | } 100 | 101 | extension IPv4Address: Equatable, Hashable { 102 | // MARK: Conformance to `Hashable` 103 | 104 | public static func == (lhs: IPv4Address, rhs: IPv4Address) -> Bool { 105 | return lhs.address.s_addr == rhs.address.s_addr 106 | } 107 | 108 | public func hash(into hasher: inout Hasher) { 109 | hasher.combine(Int(address.s_addr)) 110 | } 111 | } 112 | 113 | extension IPv4Address: ExpressibleByIntegerLiteral { 114 | // MARK: Conformance to `ExpressibleByIntegerLiteral` 115 | public init(integerLiteral value: UInt32) { 116 | self.init(value) 117 | } 118 | } 119 | 120 | public struct IPv6Address: IPAddress { 121 | public let address: in6_addr 122 | 123 | public init(address: in6_addr) { 124 | self.address = address 125 | } 126 | 127 | public init?(_ presentation: String) { 128 | var address = in6_addr() 129 | guard inet_pton(AF_INET6, presentation, &address) == 1 else { 130 | return nil 131 | } 132 | self.address = address 133 | } 134 | 135 | public init?(_ networkBytes: Data) { 136 | guard networkBytes.count == MemoryLayout.size else { 137 | return nil 138 | } 139 | self.address = networkBytes.withUnsafeBytes({ (rawBufferPointer: UnsafeRawBufferPointer) -> in6_addr in 140 | // Convert UnsafeRawBufferPointer to UnsafeBufferPointer 141 | let bufferPointer = rawBufferPointer.bindMemory(to: UInt8.self) 142 | // Convert UnsafeBufferPointer to UnsafePointer 143 | if let bytesPointer = bufferPointer.baseAddress?.withMemoryRebound(to: UInt8.self, capacity: networkBytes.count, { return $0 }) { 144 | return bytesPointer.withMemoryRebound(to: in6_addr.self, capacity: 1) { $0.pointee } 145 | } 146 | return in6_addr() 147 | }) 148 | } 149 | 150 | /// Format this IPv6 address using common `a:b:c:d:e:f:g:h` notation. 151 | public var presentationString: String? { 152 | let length = Int(INET6_ADDRSTRLEN) 153 | var presentationBytes = [CChar](repeating: 0, count: length) 154 | var addr = self.address 155 | guard inet_ntop(AF_INET6, &addr, &presentationBytes, socklen_t(length)) != nil else { 156 | return nil 157 | } 158 | return String(cString: presentationBytes) 159 | } 160 | 161 | public var presentation: String { 162 | return presentationString ?? "Invalid IPv6 address" 163 | } 164 | 165 | public var bytes: Data { 166 | #if os(Linux) 167 | return 168 | htonl(address.__in6_u.__u6_addr32.0).bytes + 169 | htonl(address.__in6_u.__u6_addr32.1).bytes + 170 | htonl(address.__in6_u.__u6_addr32.2).bytes + 171 | htonl(address.__in6_u.__u6_addr32.3).bytes 172 | #else 173 | return 174 | htonl(address.__u6_addr.__u6_addr32.0).bytes + 175 | htonl(address.__u6_addr.__u6_addr32.1).bytes + 176 | htonl(address.__u6_addr.__u6_addr32.2).bytes + 177 | htonl(address.__u6_addr.__u6_addr32.3).bytes 178 | #endif 179 | } 180 | } 181 | 182 | extension IPv6Address: Equatable, Hashable { 183 | // MARK: Conformance to `Hashable` 184 | 185 | public static func == (lhs: IPv6Address, rhs: IPv6Address) -> Bool { 186 | return lhs.presentation == rhs.presentation 187 | } 188 | 189 | public func hash(into hasher: inout Hasher) { 190 | hasher.combine(presentation.hashValue) 191 | } 192 | } 193 | #endif 194 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/NetworkService+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkService+Ext.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | #if os(Linux) 10 | import NetService 11 | #else 12 | import Network 13 | #endif 14 | 15 | #if os(Linux) 16 | protocol NetServiceProtocol: Hashable {} 17 | #else 18 | protocol NetServiceProtocol {} 19 | #endif 20 | 21 | extension NetService: NetServiceProtocol { 22 | public class func dictionary(fromTXTRecord data: Data) -> [String: String] { 23 | return NetService.dictionary(fromTXTRecord: data).mapValues { data in 24 | String(data: data, encoding: .utf8) ?? "" 25 | } 26 | } 27 | 28 | public class func data(fromTXTRecord data: [String: String]) -> Data { 29 | return NetService.data(fromTXTRecord: data.mapValues { $0.data(using: .utf8) ?? Data() }) 30 | } 31 | 32 | public func setTXTRecord(dictionary: [String: String]?) { 33 | guard let dictionary = dictionary else { 34 | _ = self.setTXTRecord(nil) 35 | return 36 | } 37 | _ = self.setTXTRecord(NetService.data(fromTXTRecord: dictionary)) 38 | } 39 | 40 | public var txtRecordDictionary: [String: String]? { 41 | guard let data = self.txtRecordData() else { return nil } 42 | return NetService.dictionary(fromTXTRecord: data) 43 | } 44 | 45 | @available(macOS 10.14, iOS 12.0, watchOS 5.0, tvOS 12.0, *) 46 | public var ipAddresses: [IPAddress] { 47 | var ipAddrs = [IPAddress]() 48 | guard let addresses = addresses else { 49 | return ipAddrs 50 | } 51 | for sockAddrData in addresses { 52 | if sockAddrData.count == MemoryLayout.size { 53 | let sockAddrBytes = UnsafeMutableBufferPointer.allocate(capacity: sockAddrData.count) 54 | assert(sockAddrData.copyBytes(to: sockAddrBytes) == MemoryLayout.size) 55 | if var sinAddr = sockAddrBytes.baseAddress?.pointee.sin_addr, 56 | let ipAddr = IPv4Address(Data(bytes: &sinAddr.s_addr, count: MemoryLayout.size)) 57 | { 58 | ipAddrs.append(ipAddr) 59 | } 60 | } else if sockAddrData.count == MemoryLayout.size { 61 | let sockAddrBytes = UnsafeMutableBufferPointer.allocate(capacity: sockAddrData.count) 62 | assert(sockAddrData.copyBytes(to: sockAddrBytes) == MemoryLayout.size) 63 | if var sinAddr = sockAddrBytes.baseAddress?.pointee.sin6_addr, 64 | let ipAddr = IPv6Address(Data(bytes: &sinAddr, count: MemoryLayout.size)) 65 | { 66 | ipAddrs.append(ipAddr) 67 | } 68 | } 69 | } 70 | return ipAddrs 71 | } 72 | 73 | #if os(Linux) 74 | public func hash(into hasher: inout Hasher) { 75 | hasher.combine(self.name) 76 | hasher.combine(self.type) 77 | hasher.combine(self.domain) 78 | } 79 | #endif 80 | 81 | #if os(Linux) 82 | public static func == (lhs: NetService, rhs: NetService) -> Bool { 83 | return lhs.name == rhs.name && lhs.type == rhs.type && lhs.domain == rhs.domain 84 | } 85 | #endif 86 | } 87 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/ServiceType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServiceType.swift 3 | // SwiftBonjour 4 | // 5 | // Created by Rachel on 2021/5/18. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum ServiceType { 11 | case tcp(String) 12 | case udp(String) 13 | 14 | public var description: String { 15 | switch self { 16 | case .tcp(let name): 17 | return "_\(name)._tcp." 18 | case .udp(let name): 19 | return "_\(name)._udp." 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/SwiftBonjour/SwiftBonjour.swift: -------------------------------------------------------------------------------- 1 | // placeholder 2 | -------------------------------------------------------------------------------- /SwiftBonjour.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SwiftBonjour.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftBonjour.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "AttributedText", 6 | "repositoryURL": "https://github.com/gonzalezreal/AttributedText", 7 | "state": { 8 | "branch": null, 9 | "revision": "c345033e22d5a1cd0e9fe0ec405cc809a8349586", 10 | "version": "0.3.1" 11 | } 12 | }, 13 | { 14 | "package": "combine-schedulers", 15 | "repositoryURL": "https://github.com/pointfreeco/combine-schedulers", 16 | "state": { 17 | "branch": null, 18 | "revision": "ec62f32d21584214a4b27c8cee2b2ad70ab2c38a", 19 | "version": "0.11.0" 20 | } 21 | }, 22 | { 23 | "package": "MarkdownUI", 24 | "repositoryURL": "https://github.com/gonzalezreal/MarkdownUI.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "29d94710545952dd4c724cc2ca901848eef54ded", 28 | "version": "0.5.2" 29 | } 30 | }, 31 | { 32 | "package": "NetworkImage", 33 | "repositoryURL": "https://github.com/gonzalezreal/NetworkImage", 34 | "state": { 35 | "branch": null, 36 | "revision": "04167e81ed89a14b5da9b856ead306b969bb5abd", 37 | "version": "3.1.2" 38 | } 39 | }, 40 | { 41 | "package": "cmark", 42 | "repositoryURL": "https://github.com/SwiftDocOrg/swift-cmark.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "9c8096a23f44794bde297452d87c455fc4f76d42", 46 | "version": "0.29.0+20210102.9c8096a" 47 | } 48 | }, 49 | { 50 | "package": "swift-concurrency-extras", 51 | "repositoryURL": "https://github.com/pointfreeco/swift-concurrency-extras", 52 | "state": { 53 | "branch": null, 54 | "revision": "479750bd98fac2e813fffcf2af0728b5b0085795", 55 | "version": "0.1.1" 56 | } 57 | }, 58 | { 59 | "package": "SwiftCommonMark", 60 | "repositoryURL": "https://github.com/gonzalezreal/SwiftCommonMark", 61 | "state": { 62 | "branch": null, 63 | "revision": "ed60da54305c244d0f77bc8d08495e04161e96a4", 64 | "version": "0.1.2" 65 | } 66 | }, 67 | { 68 | "package": "xctest-dynamic-overlay", 69 | "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay", 70 | "state": { 71 | "branch": null, 72 | "revision": "50843cbb8551db836adec2290bb4bc6bac5c1865", 73 | "version": "0.9.0" 74 | } 75 | } 76 | ] 77 | }, 78 | "version": 1 79 | } 80 | -------------------------------------------------------------------------------- /SwiftBonjourExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0FBAD4442B3F160200803B31 /* SwiftBonjour in Frameworks */ = {isa = PBXBuildFile; productRef = 0FBAD4432B3F160200803B31 /* SwiftBonjour */; }; 11 | 0FBAD4462B3F160C00803B31 /* SwiftBonjour in Frameworks */ = {isa = PBXBuildFile; productRef = 0FBAD4452B3F160C00803B31 /* SwiftBonjour */; }; 12 | 0FBAD4482B3F160F00803B31 /* SwiftBonjour in Frameworks */ = {isa = PBXBuildFile; productRef = 0FBAD4472B3F160F00803B31 /* SwiftBonjour */; }; 13 | 0FBAD44A2B3F161400803B31 /* SwiftBonjour in Frameworks */ = {isa = PBXBuildFile; productRef = 0FBAD4492B3F161400803B31 /* SwiftBonjour */; }; 14 | CCAAF31E2656347400D79B20 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = CCAAF31D2656347400D79B20 /* MarkdownUI */; }; 15 | CCAAF3202656347F00D79B20 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = CCAAF31F2656347F00D79B20 /* MarkdownUI */; }; 16 | CCAAF3A4265646C300D79B20 /* AppleComputer.txt in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF377265646C300D79B20 /* AppleComputer.txt */; }; 17 | CCAAF3A5265646C300D79B20 /* AppleComputer.txt in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF377265646C300D79B20 /* AppleComputer.txt */; }; 18 | CCAAF3A6265646C300D79B20 /* ServiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF378265646C300D79B20 /* ServiceView.swift */; }; 19 | CCAAF3A7265646C300D79B20 /* ServiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF378265646C300D79B20 /* ServiceView.swift */; }; 20 | CCAAF3AA265646C300D79B20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF379265646C300D79B20 /* Assets.xcassets */; }; 21 | CCAAF3AB265646C300D79B20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF379265646C300D79B20 /* Assets.xcassets */; }; 22 | CCAAF3AC265646C300D79B20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF379265646C300D79B20 /* Assets.xcassets */; }; 23 | CCAAF3AD265646C300D79B20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCAAF379265646C300D79B20 /* Assets.xcassets */; }; 24 | CCAAF3B0265646C300D79B20 /* BrowserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37A265646C300D79B20 /* BrowserState.swift */; }; 25 | CCAAF3B1265646C300D79B20 /* BrowserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37A265646C300D79B20 /* BrowserState.swift */; }; 26 | CCAAF3B4265646C300D79B20 /* DeviceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37B265646C300D79B20 /* DeviceView.swift */; }; 27 | CCAAF3B5265646C300D79B20 /* DeviceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37B265646C300D79B20 /* DeviceView.swift */; }; 28 | CCAAF3B8265646C300D79B20 /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37C265646C300D79B20 /* BrowserView.swift */; }; 29 | CCAAF3B9265646C300D79B20 /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37C265646C300D79B20 /* BrowserView.swift */; }; 30 | CCAAF3BA265646C300D79B20 /* ServiceState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37D265646C300D79B20 /* ServiceState.swift */; }; 31 | CCAAF3BB265646C300D79B20 /* ServiceState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37D265646C300D79B20 /* ServiceState.swift */; }; 32 | CCAAF3BE265646C300D79B20 /* SwiftBonjourApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */; }; 33 | CCAAF3BF265646C300D79B20 /* SwiftBonjourApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */; }; 34 | CCAAF3C0265646C300D79B20 /* SwiftBonjourApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */; }; 35 | CCAAF3C1265646C300D79B20 /* SwiftBonjourApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */; }; 36 | CCAAF3C2265646C300D79B20 /* HardwareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37F265646C300D79B20 /* HardwareModel.swift */; }; 37 | CCAAF3C3265646C300D79B20 /* HardwareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37F265646C300D79B20 /* HardwareModel.swift */; }; 38 | CCAAF3C4265646C300D79B20 /* HardwareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37F265646C300D79B20 /* HardwareModel.swift */; }; 39 | CCAAF3C5265646C300D79B20 /* HardwareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37F265646C300D79B20 /* HardwareModel.swift */; }; 40 | CCAAF3CA265646EE00D79B20 /* ServiceState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37D265646C300D79B20 /* ServiceState.swift */; }; 41 | CCAAF3CB265646EE00D79B20 /* ServiceState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAAF37D265646C300D79B20 /* ServiceState.swift */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXCopyFilesBuildPhase section */ 45 | CC0FC8E4265407AB00D8BD73 /* Embed Frameworks */ = { 46 | isa = PBXCopyFilesBuildPhase; 47 | buildActionMask = 2147483647; 48 | dstPath = ""; 49 | dstSubfolderSpec = 10; 50 | files = ( 51 | ); 52 | name = "Embed Frameworks"; 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | CC0FC8F0265407CC00D8BD73 /* Embed Frameworks */ = { 56 | isa = PBXCopyFilesBuildPhase; 57 | buildActionMask = 2147483647; 58 | dstPath = ""; 59 | dstSubfolderSpec = 10; 60 | files = ( 61 | ); 62 | name = "Embed Frameworks"; 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | CC51DFEC2654DFA1004251E3 /* Embed Frameworks */ = { 66 | isa = PBXCopyFilesBuildPhase; 67 | buildActionMask = 2147483647; 68 | dstPath = ""; 69 | dstSubfolderSpec = 10; 70 | files = ( 71 | ); 72 | name = "Embed Frameworks"; 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | CC51E0002654DFAB004251E3 /* Embed Frameworks */ = { 76 | isa = PBXCopyFilesBuildPhase; 77 | buildActionMask = 2147483647; 78 | dstPath = ""; 79 | dstSubfolderSpec = 10; 80 | files = ( 81 | ); 82 | name = "Embed Frameworks"; 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXCopyFilesBuildPhase section */ 86 | 87 | /* Begin PBXFileReference section */ 88 | CC0FC88B265404CF00D8BD73 /* SwiftBonjourExampleService.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftBonjourExampleService.app; sourceTree = BUILT_PRODUCTS_DIR; }; 89 | CC0FC893265404D000D8BD73 /* SwiftBonjourExampleService.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftBonjourExampleService.app; sourceTree = BUILT_PRODUCTS_DIR; }; 90 | CC51DFF12654DFA1004251E3 /* SwiftBonjourExampleBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftBonjourExampleBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | CC51E0052654DFAB004251E3 /* SwiftBonjourExampleBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftBonjourExampleBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 92 | CCAAF374265646C300D79B20 /* macOS.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; 93 | CCAAF375265646C300D79B20 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94 | CCAAF377265646C300D79B20 /* AppleComputer.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AppleComputer.txt; sourceTree = ""; }; 95 | CCAAF378265646C300D79B20 /* ServiceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceView.swift; sourceTree = ""; }; 96 | CCAAF379265646C300D79B20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97 | CCAAF37A265646C300D79B20 /* BrowserState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowserState.swift; sourceTree = ""; }; 98 | CCAAF37B265646C300D79B20 /* DeviceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceView.swift; sourceTree = ""; }; 99 | CCAAF37C265646C300D79B20 /* BrowserView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowserView.swift; sourceTree = ""; }; 100 | CCAAF37D265646C300D79B20 /* ServiceState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceState.swift; sourceTree = ""; }; 101 | CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftBonjourApp.swift; sourceTree = ""; }; 102 | CCAAF37F265646C300D79B20 /* HardwareModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HardwareModel.swift; sourceTree = ""; }; 103 | CCAAF381265646C300D79B20 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 104 | CCAAF3D32656473000D79B20 /* SwiftBonjour.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftBonjour.h; sourceTree = ""; }; 105 | CCAAF3D42656473000D79B20 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 106 | /* End PBXFileReference section */ 107 | 108 | /* Begin PBXFrameworksBuildPhase section */ 109 | CC0FC888265404CF00D8BD73 /* Frameworks */ = { 110 | isa = PBXFrameworksBuildPhase; 111 | buildActionMask = 2147483647; 112 | files = ( 113 | 0FBAD4462B3F160C00803B31 /* SwiftBonjour in Frameworks */, 114 | ); 115 | runOnlyForDeploymentPostprocessing = 0; 116 | }; 117 | CC0FC890265404D000D8BD73 /* Frameworks */ = { 118 | isa = PBXFrameworksBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 0FBAD4442B3F160200803B31 /* SwiftBonjour in Frameworks */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | CC51DFE72654DFA1004251E3 /* Frameworks */ = { 126 | isa = PBXFrameworksBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | 0FBAD44A2B3F161400803B31 /* SwiftBonjour in Frameworks */, 130 | CCAAF31E2656347400D79B20 /* MarkdownUI in Frameworks */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | CC51DFFB2654DFAB004251E3 /* Frameworks */ = { 135 | isa = PBXFrameworksBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | 0FBAD4482B3F160F00803B31 /* SwiftBonjour in Frameworks */, 139 | CCAAF3202656347F00D79B20 /* MarkdownUI in Frameworks */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXFrameworksBuildPhase section */ 144 | 145 | /* Begin PBXGroup section */ 146 | CC0FC87E265404CD00D8BD73 = { 147 | isa = PBXGroup; 148 | children = ( 149 | CCAAF372265646C300D79B20 /* Example */, 150 | CC0FC88C265404CF00D8BD73 /* Products */, 151 | CC0FC8EB265407CB00D8BD73 /* Frameworks */, 152 | ); 153 | sourceTree = ""; 154 | }; 155 | CC0FC88C265404CF00D8BD73 /* Products */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | CC0FC88B265404CF00D8BD73 /* SwiftBonjourExampleService.app */, 159 | CC0FC893265404D000D8BD73 /* SwiftBonjourExampleService.app */, 160 | CC51DFF12654DFA1004251E3 /* SwiftBonjourExampleBrowser.app */, 161 | CC51E0052654DFAB004251E3 /* SwiftBonjourExampleBrowser.app */, 162 | ); 163 | name = Products; 164 | sourceTree = ""; 165 | }; 166 | CC0FC8EB265407CB00D8BD73 /* Frameworks */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | ); 170 | name = Frameworks; 171 | sourceTree = ""; 172 | }; 173 | CCAAF372265646C300D79B20 /* Example */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | CCAAF3D22656473000D79B20 /* SwiftBonjour */, 177 | CCAAF376265646C300D79B20 /* Shared */, 178 | CCAAF373265646C300D79B20 /* macOS */, 179 | CCAAF380265646C300D79B20 /* iOS */, 180 | ); 181 | path = Example; 182 | sourceTree = ""; 183 | }; 184 | CCAAF373265646C300D79B20 /* macOS */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | CCAAF374265646C300D79B20 /* macOS.entitlements */, 188 | CCAAF375265646C300D79B20 /* Info.plist */, 189 | ); 190 | path = macOS; 191 | sourceTree = ""; 192 | }; 193 | CCAAF376265646C300D79B20 /* Shared */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | CCAAF379265646C300D79B20 /* Assets.xcassets */, 197 | CCAAF377265646C300D79B20 /* AppleComputer.txt */, 198 | CCAAF37D265646C300D79B20 /* ServiceState.swift */, 199 | CCAAF378265646C300D79B20 /* ServiceView.swift */, 200 | CCAAF37A265646C300D79B20 /* BrowserState.swift */, 201 | CCAAF37C265646C300D79B20 /* BrowserView.swift */, 202 | CCAAF37B265646C300D79B20 /* DeviceView.swift */, 203 | CCAAF37F265646C300D79B20 /* HardwareModel.swift */, 204 | CCAAF37E265646C300D79B20 /* SwiftBonjourApp.swift */, 205 | ); 206 | path = Shared; 207 | sourceTree = ""; 208 | }; 209 | CCAAF380265646C300D79B20 /* iOS */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | CCAAF381265646C300D79B20 /* Info.plist */, 213 | ); 214 | path = iOS; 215 | sourceTree = ""; 216 | }; 217 | CCAAF3D22656473000D79B20 /* SwiftBonjour */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | CCAAF3D32656473000D79B20 /* SwiftBonjour.h */, 221 | CCAAF3D42656473000D79B20 /* Info.plist */, 222 | ); 223 | path = SwiftBonjour; 224 | sourceTree = ""; 225 | }; 226 | /* End PBXGroup section */ 227 | 228 | /* Begin PBXNativeTarget section */ 229 | CC0FC88A265404CF00D8BD73 /* SwiftBonjourExample Service (iOS) */ = { 230 | isa = PBXNativeTarget; 231 | buildConfigurationList = CC0FC8B5265404D000D8BD73 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Service (iOS)" */; 232 | buildPhases = ( 233 | CC0FC887265404CF00D8BD73 /* Sources */, 234 | CC0FC888265404CF00D8BD73 /* Frameworks */, 235 | CC0FC889265404CF00D8BD73 /* Resources */, 236 | CC0FC8F0265407CC00D8BD73 /* Embed Frameworks */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | ); 242 | name = "SwiftBonjourExample Service (iOS)"; 243 | packageProductDependencies = ( 244 | 0FBAD4452B3F160C00803B31 /* SwiftBonjour */, 245 | ); 246 | productName = "SwiftBonjour (iOS)"; 247 | productReference = CC0FC88B265404CF00D8BD73 /* SwiftBonjourExampleService.app */; 248 | productType = "com.apple.product-type.application"; 249 | }; 250 | CC0FC892265404D000D8BD73 /* SwiftBonjourExample Service (macOS) */ = { 251 | isa = PBXNativeTarget; 252 | buildConfigurationList = CC0FC8B8265404D000D8BD73 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Service (macOS)" */; 253 | buildPhases = ( 254 | CC0FC88F265404D000D8BD73 /* Sources */, 255 | CC0FC890265404D000D8BD73 /* Frameworks */, 256 | CC0FC891265404D000D8BD73 /* Resources */, 257 | CC0FC8E4265407AB00D8BD73 /* Embed Frameworks */, 258 | ); 259 | buildRules = ( 260 | ); 261 | dependencies = ( 262 | ); 263 | name = "SwiftBonjourExample Service (macOS)"; 264 | packageProductDependencies = ( 265 | 0FBAD4432B3F160200803B31 /* SwiftBonjour */, 266 | ); 267 | productName = "SwiftBonjour (macOS)"; 268 | productReference = CC0FC893265404D000D8BD73 /* SwiftBonjourExampleService.app */; 269 | productType = "com.apple.product-type.application"; 270 | }; 271 | CC51DFDF2654DFA1004251E3 /* SwiftBonjourExample Browser (iOS) */ = { 272 | isa = PBXNativeTarget; 273 | buildConfigurationList = CC51DFEE2654DFA1004251E3 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Browser (iOS)" */; 274 | buildPhases = ( 275 | CC51DFE22654DFA1004251E3 /* Sources */, 276 | CC51DFE72654DFA1004251E3 /* Frameworks */, 277 | CC51DFE92654DFA1004251E3 /* Resources */, 278 | CC51DFEC2654DFA1004251E3 /* Embed Frameworks */, 279 | ); 280 | buildRules = ( 281 | ); 282 | dependencies = ( 283 | ); 284 | name = "SwiftBonjourExample Browser (iOS)"; 285 | packageProductDependencies = ( 286 | CCAAF31D2656347400D79B20 /* MarkdownUI */, 287 | 0FBAD4492B3F161400803B31 /* SwiftBonjour */, 288 | ); 289 | productName = "SwiftBonjour (iOS)"; 290 | productReference = CC51DFF12654DFA1004251E3 /* SwiftBonjourExampleBrowser.app */; 291 | productType = "com.apple.product-type.application"; 292 | }; 293 | CC51DFF32654DFAB004251E3 /* SwiftBonjourExample Browser (macOS) */ = { 294 | isa = PBXNativeTarget; 295 | buildConfigurationList = CC51E0022654DFAB004251E3 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Browser (macOS)" */; 296 | buildPhases = ( 297 | CC51DFF62654DFAB004251E3 /* Sources */, 298 | CC51DFFB2654DFAB004251E3 /* Frameworks */, 299 | CC51DFFD2654DFAB004251E3 /* Resources */, 300 | CC51E0002654DFAB004251E3 /* Embed Frameworks */, 301 | ); 302 | buildRules = ( 303 | ); 304 | dependencies = ( 305 | ); 306 | name = "SwiftBonjourExample Browser (macOS)"; 307 | packageProductDependencies = ( 308 | CCAAF31F2656347F00D79B20 /* MarkdownUI */, 309 | 0FBAD4472B3F160F00803B31 /* SwiftBonjour */, 310 | ); 311 | productName = "SwiftBonjour (macOS)"; 312 | productReference = CC51E0052654DFAB004251E3 /* SwiftBonjourExampleBrowser.app */; 313 | productType = "com.apple.product-type.application"; 314 | }; 315 | /* End PBXNativeTarget section */ 316 | 317 | /* Begin PBXProject section */ 318 | CC0FC87F265404CD00D8BD73 /* Project object */ = { 319 | isa = PBXProject; 320 | attributes = { 321 | LastSwiftUpdateCheck = 1250; 322 | LastUpgradeCheck = 1310; 323 | TargetAttributes = { 324 | CC0FC88A265404CF00D8BD73 = { 325 | CreatedOnToolsVersion = 12.5; 326 | }; 327 | CC0FC892265404D000D8BD73 = { 328 | CreatedOnToolsVersion = 12.5; 329 | }; 330 | }; 331 | }; 332 | buildConfigurationList = CC0FC882265404CD00D8BD73 /* Build configuration list for PBXProject "SwiftBonjourExample" */; 333 | compatibilityVersion = "Xcode 9.3"; 334 | developmentRegion = en; 335 | hasScannedForEncodings = 0; 336 | knownRegions = ( 337 | en, 338 | Base, 339 | ); 340 | mainGroup = CC0FC87E265404CD00D8BD73; 341 | packageReferences = ( 342 | CCAAF31C2656347400D79B20 /* XCRemoteSwiftPackageReference "MarkdownUI" */, 343 | ); 344 | productRefGroup = CC0FC88C265404CF00D8BD73 /* Products */; 345 | projectDirPath = ""; 346 | projectRoot = ""; 347 | targets = ( 348 | CC0FC892265404D000D8BD73 /* SwiftBonjourExample Service (macOS) */, 349 | CC0FC88A265404CF00D8BD73 /* SwiftBonjourExample Service (iOS) */, 350 | CC51DFF32654DFAB004251E3 /* SwiftBonjourExample Browser (macOS) */, 351 | CC51DFDF2654DFA1004251E3 /* SwiftBonjourExample Browser (iOS) */, 352 | ); 353 | }; 354 | /* End PBXProject section */ 355 | 356 | /* Begin PBXResourcesBuildPhase section */ 357 | CC0FC889265404CF00D8BD73 /* Resources */ = { 358 | isa = PBXResourcesBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | CCAAF3AB265646C300D79B20 /* Assets.xcassets in Resources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | CC0FC891265404D000D8BD73 /* Resources */ = { 366 | isa = PBXResourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | CCAAF3AA265646C300D79B20 /* Assets.xcassets in Resources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | CC51DFE92654DFA1004251E3 /* Resources */ = { 374 | isa = PBXResourcesBuildPhase; 375 | buildActionMask = 2147483647; 376 | files = ( 377 | CCAAF3A5265646C300D79B20 /* AppleComputer.txt in Resources */, 378 | CCAAF3AD265646C300D79B20 /* Assets.xcassets in Resources */, 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | }; 382 | CC51DFFD2654DFAB004251E3 /* Resources */ = { 383 | isa = PBXResourcesBuildPhase; 384 | buildActionMask = 2147483647; 385 | files = ( 386 | CCAAF3A4265646C300D79B20 /* AppleComputer.txt in Resources */, 387 | CCAAF3AC265646C300D79B20 /* Assets.xcassets in Resources */, 388 | ); 389 | runOnlyForDeploymentPostprocessing = 0; 390 | }; 391 | /* End PBXResourcesBuildPhase section */ 392 | 393 | /* Begin PBXSourcesBuildPhase section */ 394 | CC0FC887265404CF00D8BD73 /* Sources */ = { 395 | isa = PBXSourcesBuildPhase; 396 | buildActionMask = 2147483647; 397 | files = ( 398 | CCAAF3A7265646C300D79B20 /* ServiceView.swift in Sources */, 399 | CCAAF3BF265646C300D79B20 /* SwiftBonjourApp.swift in Sources */, 400 | CCAAF3BB265646C300D79B20 /* ServiceState.swift in Sources */, 401 | CCAAF3C3265646C300D79B20 /* HardwareModel.swift in Sources */, 402 | ); 403 | runOnlyForDeploymentPostprocessing = 0; 404 | }; 405 | CC0FC88F265404D000D8BD73 /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | CCAAF3A6265646C300D79B20 /* ServiceView.swift in Sources */, 410 | CCAAF3BE265646C300D79B20 /* SwiftBonjourApp.swift in Sources */, 411 | CCAAF3BA265646C300D79B20 /* ServiceState.swift in Sources */, 412 | CCAAF3C2265646C300D79B20 /* HardwareModel.swift in Sources */, 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | }; 416 | CC51DFE22654DFA1004251E3 /* Sources */ = { 417 | isa = PBXSourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | CCAAF3B5265646C300D79B20 /* DeviceView.swift in Sources */, 421 | CCAAF3B9265646C300D79B20 /* BrowserView.swift in Sources */, 422 | CCAAF3B1265646C300D79B20 /* BrowserState.swift in Sources */, 423 | CCAAF3C1265646C300D79B20 /* SwiftBonjourApp.swift in Sources */, 424 | CCAAF3C5265646C300D79B20 /* HardwareModel.swift in Sources */, 425 | CCAAF3CB265646EE00D79B20 /* ServiceState.swift in Sources */, 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | CC51DFF62654DFAB004251E3 /* Sources */ = { 430 | isa = PBXSourcesBuildPhase; 431 | buildActionMask = 2147483647; 432 | files = ( 433 | CCAAF3B4265646C300D79B20 /* DeviceView.swift in Sources */, 434 | CCAAF3B8265646C300D79B20 /* BrowserView.swift in Sources */, 435 | CCAAF3B0265646C300D79B20 /* BrowserState.swift in Sources */, 436 | CCAAF3C0265646C300D79B20 /* SwiftBonjourApp.swift in Sources */, 437 | CCAAF3C4265646C300D79B20 /* HardwareModel.swift in Sources */, 438 | CCAAF3CA265646EE00D79B20 /* ServiceState.swift in Sources */, 439 | ); 440 | runOnlyForDeploymentPostprocessing = 0; 441 | }; 442 | /* End PBXSourcesBuildPhase section */ 443 | 444 | /* Begin XCBuildConfiguration section */ 445 | CC0FC8B3265404D000D8BD73 /* Debug */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ALWAYS_SEARCH_USER_PATHS = NO; 449 | CLANG_ANALYZER_NONNULL = YES; 450 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 452 | CLANG_CXX_LIBRARY = "libc++"; 453 | CLANG_ENABLE_MODULES = YES; 454 | CLANG_ENABLE_OBJC_ARC = YES; 455 | CLANG_ENABLE_OBJC_WEAK = YES; 456 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 457 | CLANG_WARN_BOOL_CONVERSION = YES; 458 | CLANG_WARN_COMMA = YES; 459 | CLANG_WARN_CONSTANT_CONVERSION = YES; 460 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 461 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 462 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 463 | CLANG_WARN_EMPTY_BODY = YES; 464 | CLANG_WARN_ENUM_CONVERSION = YES; 465 | CLANG_WARN_INFINITE_RECURSION = YES; 466 | CLANG_WARN_INT_CONVERSION = YES; 467 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 468 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 469 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 471 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 472 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 473 | CLANG_WARN_STRICT_PROTOTYPES = YES; 474 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 475 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 476 | CLANG_WARN_UNREACHABLE_CODE = YES; 477 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 478 | COPY_PHASE_STRIP = NO; 479 | DEBUG_INFORMATION_FORMAT = dwarf; 480 | ENABLE_STRICT_OBJC_MSGSEND = YES; 481 | ENABLE_TESTABILITY = YES; 482 | GCC_C_LANGUAGE_STANDARD = gnu11; 483 | GCC_DYNAMIC_NO_PIC = NO; 484 | GCC_NO_COMMON_BLOCKS = YES; 485 | GCC_OPTIMIZATION_LEVEL = 0; 486 | GCC_PREPROCESSOR_DEFINITIONS = ( 487 | "DEBUG=1", 488 | "$(inherited)", 489 | ); 490 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 491 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 492 | GCC_WARN_UNDECLARED_SELECTOR = YES; 493 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 494 | GCC_WARN_UNUSED_FUNCTION = YES; 495 | GCC_WARN_UNUSED_VARIABLE = YES; 496 | IPHONEOS_DEPLOYMENT_TARGET = 14.1; 497 | MACOSX_DEPLOYMENT_TARGET = 11.0; 498 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 499 | MTL_FAST_MATH = YES; 500 | ONLY_ACTIVE_ARCH = YES; 501 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 502 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 503 | TARGETED_DEVICE_FAMILY = "1,2,3,4,5,6"; 504 | TVOS_DEPLOYMENT_TARGET = 14.1; 505 | WATCHOS_DEPLOYMENT_TARGET = 7.1; 506 | }; 507 | name = Debug; 508 | }; 509 | CC0FC8B4265404D000D8BD73 /* Release */ = { 510 | isa = XCBuildConfiguration; 511 | buildSettings = { 512 | ALWAYS_SEARCH_USER_PATHS = NO; 513 | CLANG_ANALYZER_NONNULL = YES; 514 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 515 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 516 | CLANG_CXX_LIBRARY = "libc++"; 517 | CLANG_ENABLE_MODULES = YES; 518 | CLANG_ENABLE_OBJC_ARC = YES; 519 | CLANG_ENABLE_OBJC_WEAK = YES; 520 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 521 | CLANG_WARN_BOOL_CONVERSION = YES; 522 | CLANG_WARN_COMMA = YES; 523 | CLANG_WARN_CONSTANT_CONVERSION = YES; 524 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 525 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 526 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 527 | CLANG_WARN_EMPTY_BODY = YES; 528 | CLANG_WARN_ENUM_CONVERSION = YES; 529 | CLANG_WARN_INFINITE_RECURSION = YES; 530 | CLANG_WARN_INT_CONVERSION = YES; 531 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 532 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 533 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 534 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 535 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 536 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 537 | CLANG_WARN_STRICT_PROTOTYPES = YES; 538 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 539 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 540 | CLANG_WARN_UNREACHABLE_CODE = YES; 541 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 542 | COPY_PHASE_STRIP = NO; 543 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 544 | ENABLE_NS_ASSERTIONS = NO; 545 | ENABLE_STRICT_OBJC_MSGSEND = YES; 546 | GCC_C_LANGUAGE_STANDARD = gnu11; 547 | GCC_NO_COMMON_BLOCKS = YES; 548 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 549 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 550 | GCC_WARN_UNDECLARED_SELECTOR = YES; 551 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 552 | GCC_WARN_UNUSED_FUNCTION = YES; 553 | GCC_WARN_UNUSED_VARIABLE = YES; 554 | IPHONEOS_DEPLOYMENT_TARGET = 14.1; 555 | MACOSX_DEPLOYMENT_TARGET = 11.0; 556 | MTL_ENABLE_DEBUG_INFO = NO; 557 | MTL_FAST_MATH = YES; 558 | SWIFT_COMPILATION_MODE = wholemodule; 559 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 560 | TARGETED_DEVICE_FAMILY = "1,2,3,4,5,6"; 561 | TVOS_DEPLOYMENT_TARGET = 14.1; 562 | WATCHOS_DEPLOYMENT_TARGET = 7.1; 563 | }; 564 | name = Release; 565 | }; 566 | CC0FC8B6265404D000D8BD73 /* Debug */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 570 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 571 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 572 | CODE_SIGN_STYLE = Automatic; 573 | DEVELOPMENT_TEAM = ""; 574 | ENABLE_PREVIEWS = YES; 575 | GCC_PREPROCESSOR_DEFINITIONS = ( 576 | "$(inherited)", 577 | "SERVICE=1", 578 | ); 579 | INFOPLIST_FILE = Example/iOS/Info.plist; 580 | LD_RUNPATH_SEARCH_PATHS = ( 581 | "$(inherited)", 582 | "@executable_path/Frameworks", 583 | ); 584 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Service; 585 | PRODUCT_NAME = SwiftBonjourExampleService; 586 | SDKROOT = iphoneos; 587 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SERVICE"; 588 | SWIFT_VERSION = 5.0; 589 | TARGETED_DEVICE_FAMILY = "1,2"; 590 | }; 591 | name = Debug; 592 | }; 593 | CC0FC8B7265404D000D8BD73 /* Release */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 597 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 598 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 599 | CODE_SIGN_STYLE = Automatic; 600 | DEVELOPMENT_TEAM = ""; 601 | ENABLE_PREVIEWS = YES; 602 | GCC_PREPROCESSOR_DEFINITIONS = "SERVICE=1"; 603 | INFOPLIST_FILE = Example/iOS/Info.plist; 604 | LD_RUNPATH_SEARCH_PATHS = ( 605 | "$(inherited)", 606 | "@executable_path/Frameworks", 607 | ); 608 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Service; 609 | PRODUCT_NAME = SwiftBonjourExampleService; 610 | SDKROOT = iphoneos; 611 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = SERVICE; 612 | SWIFT_VERSION = 5.0; 613 | TARGETED_DEVICE_FAMILY = "1,2"; 614 | VALIDATE_PRODUCT = YES; 615 | }; 616 | name = Release; 617 | }; 618 | CC0FC8B9265404D000D8BD73 /* Debug */ = { 619 | isa = XCBuildConfiguration; 620 | buildSettings = { 621 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 622 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 623 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 624 | CODE_SIGN_ENTITLEMENTS = Example/macOS/macOS.entitlements; 625 | CODE_SIGN_IDENTITY = "Apple Development"; 626 | CODE_SIGN_STYLE = Automatic; 627 | COMBINE_HIDPI_IMAGES = YES; 628 | DEVELOPMENT_TEAM = ""; 629 | ENABLE_HARDENED_RUNTIME = YES; 630 | ENABLE_PREVIEWS = YES; 631 | GCC_PREPROCESSOR_DEFINITIONS = ( 632 | "$(inherited)", 633 | "SERVICE=1", 634 | ); 635 | INFOPLIST_FILE = Example/macOS/Info.plist; 636 | LD_RUNPATH_SEARCH_PATHS = ( 637 | "$(inherited)", 638 | "@executable_path/../Frameworks", 639 | ); 640 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Service; 641 | PRODUCT_NAME = SwiftBonjourExampleService; 642 | SDKROOT = macosx; 643 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG SERVICE"; 644 | SWIFT_VERSION = 5.0; 645 | TARGETED_DEVICE_FAMILY = 6; 646 | }; 647 | name = Debug; 648 | }; 649 | CC0FC8BA265404D000D8BD73 /* Release */ = { 650 | isa = XCBuildConfiguration; 651 | buildSettings = { 652 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 653 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 654 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 655 | CODE_SIGN_ENTITLEMENTS = Example/macOS/macOS.entitlements; 656 | CODE_SIGN_IDENTITY = "Apple Development"; 657 | CODE_SIGN_STYLE = Automatic; 658 | COMBINE_HIDPI_IMAGES = YES; 659 | DEVELOPMENT_TEAM = ""; 660 | ENABLE_HARDENED_RUNTIME = YES; 661 | ENABLE_PREVIEWS = YES; 662 | GCC_PREPROCESSOR_DEFINITIONS = "SERVICE=1"; 663 | INFOPLIST_FILE = Example/macOS/Info.plist; 664 | LD_RUNPATH_SEARCH_PATHS = ( 665 | "$(inherited)", 666 | "@executable_path/../Frameworks", 667 | ); 668 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Service; 669 | PRODUCT_NAME = SwiftBonjourExampleService; 670 | SDKROOT = macosx; 671 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = SERVICE; 672 | SWIFT_VERSION = 5.0; 673 | TARGETED_DEVICE_FAMILY = 6; 674 | }; 675 | name = Release; 676 | }; 677 | CC51DFEF2654DFA1004251E3 /* Debug */ = { 678 | isa = XCBuildConfiguration; 679 | buildSettings = { 680 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 681 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 682 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 683 | CODE_SIGN_STYLE = Automatic; 684 | DEVELOPMENT_TEAM = ""; 685 | ENABLE_PREVIEWS = YES; 686 | INFOPLIST_FILE = Example/iOS/Info.plist; 687 | LD_RUNPATH_SEARCH_PATHS = ( 688 | "$(inherited)", 689 | "@executable_path/Frameworks", 690 | ); 691 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Browser; 692 | PRODUCT_NAME = SwiftBonjourExampleBrowser; 693 | SDKROOT = iphoneos; 694 | SWIFT_VERSION = 5.0; 695 | TARGETED_DEVICE_FAMILY = "1,2"; 696 | }; 697 | name = Debug; 698 | }; 699 | CC51DFF02654DFA1004251E3 /* Release */ = { 700 | isa = XCBuildConfiguration; 701 | buildSettings = { 702 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 703 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 704 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 705 | CODE_SIGN_STYLE = Automatic; 706 | DEVELOPMENT_TEAM = ""; 707 | ENABLE_PREVIEWS = YES; 708 | INFOPLIST_FILE = Example/iOS/Info.plist; 709 | LD_RUNPATH_SEARCH_PATHS = ( 710 | "$(inherited)", 711 | "@executable_path/Frameworks", 712 | ); 713 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Browser; 714 | PRODUCT_NAME = SwiftBonjourExampleBrowser; 715 | SDKROOT = iphoneos; 716 | SWIFT_VERSION = 5.0; 717 | TARGETED_DEVICE_FAMILY = "1,2"; 718 | VALIDATE_PRODUCT = YES; 719 | }; 720 | name = Release; 721 | }; 722 | CC51E0032654DFAB004251E3 /* Debug */ = { 723 | isa = XCBuildConfiguration; 724 | buildSettings = { 725 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 726 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 727 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 728 | CODE_SIGN_ENTITLEMENTS = Example/macOS/macOS.entitlements; 729 | CODE_SIGN_IDENTITY = "Apple Development"; 730 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 731 | CODE_SIGN_STYLE = Automatic; 732 | COMBINE_HIDPI_IMAGES = YES; 733 | DEVELOPMENT_TEAM = ""; 734 | ENABLE_HARDENED_RUNTIME = YES; 735 | ENABLE_PREVIEWS = YES; 736 | INFOPLIST_FILE = Example/macOS/Info.plist; 737 | LD_RUNPATH_SEARCH_PATHS = ( 738 | "$(inherited)", 739 | "@executable_path/../Frameworks", 740 | ); 741 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Browser; 742 | PRODUCT_NAME = SwiftBonjourExampleBrowser; 743 | SDKROOT = macosx; 744 | SWIFT_VERSION = 5.0; 745 | TARGETED_DEVICE_FAMILY = 6; 746 | }; 747 | name = Debug; 748 | }; 749 | CC51E0042654DFAB004251E3 /* Release */ = { 750 | isa = XCBuildConfiguration; 751 | buildSettings = { 752 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 753 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 754 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 755 | CODE_SIGN_ENTITLEMENTS = Example/macOS/macOS.entitlements; 756 | CODE_SIGN_IDENTITY = "Apple Development"; 757 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 758 | CODE_SIGN_STYLE = Automatic; 759 | COMBINE_HIDPI_IMAGES = YES; 760 | DEVELOPMENT_TEAM = ""; 761 | ENABLE_HARDENED_RUNTIME = YES; 762 | ENABLE_PREVIEWS = YES; 763 | INFOPLIST_FILE = Example/macOS/Info.plist; 764 | LD_RUNPATH_SEARCH_PATHS = ( 765 | "$(inherited)", 766 | "@executable_path/../Frameworks", 767 | ); 768 | PRODUCT_BUNDLE_IDENTIFIER = com.darwindev.SwiftBonjour.Browser; 769 | PRODUCT_NAME = SwiftBonjourExampleBrowser; 770 | SDKROOT = macosx; 771 | SWIFT_VERSION = 5.0; 772 | TARGETED_DEVICE_FAMILY = 6; 773 | }; 774 | name = Release; 775 | }; 776 | /* End XCBuildConfiguration section */ 777 | 778 | /* Begin XCConfigurationList section */ 779 | CC0FC882265404CD00D8BD73 /* Build configuration list for PBXProject "SwiftBonjourExample" */ = { 780 | isa = XCConfigurationList; 781 | buildConfigurations = ( 782 | CC0FC8B3265404D000D8BD73 /* Debug */, 783 | CC0FC8B4265404D000D8BD73 /* Release */, 784 | ); 785 | defaultConfigurationIsVisible = 0; 786 | defaultConfigurationName = Release; 787 | }; 788 | CC0FC8B5265404D000D8BD73 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Service (iOS)" */ = { 789 | isa = XCConfigurationList; 790 | buildConfigurations = ( 791 | CC0FC8B6265404D000D8BD73 /* Debug */, 792 | CC0FC8B7265404D000D8BD73 /* Release */, 793 | ); 794 | defaultConfigurationIsVisible = 0; 795 | defaultConfigurationName = Release; 796 | }; 797 | CC0FC8B8265404D000D8BD73 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Service (macOS)" */ = { 798 | isa = XCConfigurationList; 799 | buildConfigurations = ( 800 | CC0FC8B9265404D000D8BD73 /* Debug */, 801 | CC0FC8BA265404D000D8BD73 /* Release */, 802 | ); 803 | defaultConfigurationIsVisible = 0; 804 | defaultConfigurationName = Release; 805 | }; 806 | CC51DFEE2654DFA1004251E3 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Browser (iOS)" */ = { 807 | isa = XCConfigurationList; 808 | buildConfigurations = ( 809 | CC51DFEF2654DFA1004251E3 /* Debug */, 810 | CC51DFF02654DFA1004251E3 /* Release */, 811 | ); 812 | defaultConfigurationIsVisible = 0; 813 | defaultConfigurationName = Release; 814 | }; 815 | CC51E0022654DFAB004251E3 /* Build configuration list for PBXNativeTarget "SwiftBonjourExample Browser (macOS)" */ = { 816 | isa = XCConfigurationList; 817 | buildConfigurations = ( 818 | CC51E0032654DFAB004251E3 /* Debug */, 819 | CC51E0042654DFAB004251E3 /* Release */, 820 | ); 821 | defaultConfigurationIsVisible = 0; 822 | defaultConfigurationName = Release; 823 | }; 824 | /* End XCConfigurationList section */ 825 | 826 | /* Begin XCRemoteSwiftPackageReference section */ 827 | CCAAF31C2656347400D79B20 /* XCRemoteSwiftPackageReference "MarkdownUI" */ = { 828 | isa = XCRemoteSwiftPackageReference; 829 | repositoryURL = "https://github.com/gonzalezreal/MarkdownUI.git"; 830 | requirement = { 831 | kind = upToNextMajorVersion; 832 | minimumVersion = 0.5.1; 833 | }; 834 | }; 835 | /* End XCRemoteSwiftPackageReference section */ 836 | 837 | /* Begin XCSwiftPackageProductDependency section */ 838 | 0FBAD4432B3F160200803B31 /* SwiftBonjour */ = { 839 | isa = XCSwiftPackageProductDependency; 840 | productName = SwiftBonjour; 841 | }; 842 | 0FBAD4452B3F160C00803B31 /* SwiftBonjour */ = { 843 | isa = XCSwiftPackageProductDependency; 844 | productName = SwiftBonjour; 845 | }; 846 | 0FBAD4472B3F160F00803B31 /* SwiftBonjour */ = { 847 | isa = XCSwiftPackageProductDependency; 848 | productName = SwiftBonjour; 849 | }; 850 | 0FBAD4492B3F161400803B31 /* SwiftBonjour */ = { 851 | isa = XCSwiftPackageProductDependency; 852 | productName = SwiftBonjour; 853 | }; 854 | CCAAF31D2656347400D79B20 /* MarkdownUI */ = { 855 | isa = XCSwiftPackageProductDependency; 856 | package = CCAAF31C2656347400D79B20 /* XCRemoteSwiftPackageReference "MarkdownUI" */; 857 | productName = MarkdownUI; 858 | }; 859 | CCAAF31F2656347F00D79B20 /* MarkdownUI */ = { 860 | isa = XCSwiftPackageProductDependency; 861 | package = CCAAF31C2656347400D79B20 /* XCRemoteSwiftPackageReference "MarkdownUI" */; 862 | productName = MarkdownUI; 863 | }; 864 | /* End XCSwiftPackageProductDependency section */ 865 | }; 866 | rootObject = CC0FC87F265404CD00D8BD73 /* Project object */; 867 | } 868 | -------------------------------------------------------------------------------- /SwiftBonjourExample.xcodeproj/xcshareddata/xcschemes/SwiftBonjour Browser (iOS).xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SwiftBonjourExample.xcodeproj/xcshareddata/xcschemes/SwiftBonjour Browser (macOS).xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SwiftBonjourExample.xcodeproj/xcshareddata/xcschemes/SwiftBonjour Service (iOS).xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SwiftBonjourExample.xcodeproj/xcshareddata/xcschemes/SwiftBonjour Service (macOS).xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | --------------------------------------------------------------------------------