├── .github ├── FUNDING.yml └── workflows │ └── swift.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Editable Graphics ├── bb.png ├── bb.svg ├── bk.png ├── bk.svg ├── bn.png ├── bn.svg ├── bp.png ├── bp.svg ├── bq.png ├── bq.svg ├── br.png ├── br.svg ├── wb.png ├── wb.svg ├── wk.png ├── wk.svg ├── wn.png ├── wn.svg ├── wp.png ├── wp.svg ├── wq.png ├── wq.svg ├── wr.png └── wr.svg ├── FDChessboardView.podspec ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── FDChessboardView │ ├── FDChessboardImageData.swift │ ├── FDChessboardPiece.swift │ └── FDChessboardView.swift ├── Tests ├── CheckCocoaPodsQualityIndexes.rb ├── FDChessboardViewTests │ ├── FDChessboardViewTests.swift │ └── XCTestManifests.swift └── LinuxMain.swift └── iOS Example ├── Sources ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SceneDelegate.swift └── ViewController.swift ├── iOS Example.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist └── iOS Example.xcworkspace ├── contents.xcworkspacedata └── xcshareddata └── IDEWorkspaceChecks.plist /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [fulldecent] 4 | custom: ["https://www.paypal.me/fulldecent", "https://amazon.com/hz/wishlist/ls/EE78A23EEGQB"] 5 | -------------------------------------------------------------------------------- /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | name: Swift 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: macOS-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Build 13 | run: swift build -v 14 | - name: Run tests 15 | run: swift test -v 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | 92 | FDChessboardView.framework.zip 93 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7.3 3 | env: 4 | global: 5 | - LC_CTYPE=en_US.UTF-8 6 | - LANG=en_US.UTF-8 7 | - WORKSPACE=FDChessboardView.xcworkspace 8 | - IOS_FRAMEWORK_SCHEME="FDChessboardView" 9 | - IOS_SDK=iphonesimulator9.3 10 | - EXAMPLE_SCHEME="iOS Example" 11 | matrix: 12 | - DESTINATION="OS=9.3,name=iPhone 6S Plus" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" POD_LINT="NO" 13 | script: 14 | - set -o pipefail 15 | - xcodebuild -version 16 | - xcodebuild -showsdks 17 | - xcodebuild -list 18 | - xcodebuild -workspace "$WORKSPACE" -list 19 | 20 | # Build and test Framework in Debug 21 | - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty 22 | 23 | # Build Framework in ReleaseTest 24 | - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration ReleaseTest ONLY_ACTIVE_ARCH=NO build | xcpretty 25 | 26 | # Build Example in Debug if specified 27 | - xcodebuild -workspace "$WORKSPACE" -scheme "$EXAMPLE_SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty 28 | 29 | # Run `pod lib lint` if specified 30 | - if [ $POD_LINT == "YES" ]; then 31 | pod lib lint; 32 | fi 33 | 34 | # Test CocoaPods quality scores are met 35 | - ruby Tests/CheckCocoaPodsQualityIndexes.rb 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | `FDChessboardView` adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | --- 6 | 7 | ## [Master](https://github.com/fulldecent/FDChessboardView/compare/4.0.0...master) 8 | 9 | --- 10 | 11 | ## [3.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/4.0.0) 12 | Released on 2019-11-04. 13 | 14 | #### Added 15 | - Full support for Swift Package Manager 16 | 17 | --- 18 | 19 | ## [2.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/2.0.0) 20 | Released on 2019-04-08. 21 | 22 | #### Added 23 | - Support for Swift 5 24 | 25 | --- 26 | 27 | ## [1.1.0](https://github.com/fulldecent/FDChessboardView/releases/tag/1.1.0) 28 | Released on 2018-01-29. 29 | 30 | #### Added 31 | - Support for Swift 4 32 | - Support for the Forsyth–Edwards Notation 33 | - Added by [David Airapetyan](https://github.com/davidair). 34 | 35 | --- 36 | 37 | ## [1.0.0](https://github.com/fulldecent/FDChessboardView/releases/tag/1.0.0) 38 | Released on 2016-12-05. 39 | 40 | #### Changed 41 | 42 | - Update project settings from Xcode recommendation 43 | 44 | --- 45 | 46 | ## [0.4.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.4.0) 47 | Released on 2016-09-10. 48 | 49 | #### Changed 50 | 51 | - Updated project for Swift 3 52 | 53 | --- 54 | 55 | ## [0.3.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.3.0) 56 | Released on 2016-06-27. 57 | 58 | #### Added 59 | - Added IBInspectable / IBDesignable 60 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue 61 | [#11](https://github.com/fulldecent/FDBarGuage/issues/11). 62 | - Full API documentation 63 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue 64 | [#6](https://github.com/fulldecent/FDBarGuage/issues/6). 65 | - Documented release process 66 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue 67 | [#10](https://github.com/fulldecent/FDBarGuage/issues/10). 68 | - Change Log 69 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue 70 | [#7](https://github.com/fulldecent/FDBarGuage/issues/7). 71 | 72 | --- 73 | 74 | ## [0.2.0](https://github.com/fulldecent/FDChessboardView/releases/tag/0.2.0) 75 | Released on 2016-05-01. 76 | 77 | #### Added 78 | - Support for Carthage and SPM 79 | - Added by [William Entriken](https://github.com/fulldecent) in Regards to Issue 80 | [#4](https://github.com/fulldecent/FDBarGuage/issues/4). 81 | 82 | --- 83 | 84 | ## [01.10](https://github.com/fulldecent/FDChessboardView/releases/tag/0.1.0) 85 | Released on 2016-06-26. 86 | 87 | Initial public release. 88 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | All contributors are welcome. Please use issues and pull requests to contribute to the project. And update [CHANGELOG.md](CHANGELOG.md) when committing. 4 | 5 | # Release Process 6 | 7 | 1. Confirm the build is passing in travis 8 | 1. This automatically checks the pod file is building 9 | 2. Create a release commit, see [prior releases](https://github.com/fulldecent/FDChessboardView/releases) for an example 10 | 1. Update the change log to label the latest improvements under the new version name 11 | 2. Update the podspec version number 12 | 3. Tag the release in GitHub 13 | 1. Create the release commit 14 | 2. Create the release with notes from the change log 15 | 3. Push the podspec to cocoapods 16 | 1. `pod trunk push` 17 | 4. Create Carthage binaries 18 | 1. `carthage build --no-skip-current` 19 | 2. `carthage archive FDChessboardView` 20 | 3. Add to the GitHub release 21 | -------------------------------------------------------------------------------- /Editable Graphics/bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bb.png -------------------------------------------------------------------------------- /Editable Graphics/bb.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/bk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bk.png -------------------------------------------------------------------------------- /Editable Graphics/bk.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/bn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bn.png -------------------------------------------------------------------------------- /Editable Graphics/bn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/bp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bp.png -------------------------------------------------------------------------------- /Editable Graphics/bp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/bq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/bq.png -------------------------------------------------------------------------------- /Editable Graphics/bq.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/br.png -------------------------------------------------------------------------------- /Editable Graphics/br.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wb.png -------------------------------------------------------------------------------- /Editable Graphics/wb.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wk.png -------------------------------------------------------------------------------- /Editable Graphics/wk.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wn.png -------------------------------------------------------------------------------- /Editable Graphics/wn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wp.png -------------------------------------------------------------------------------- /Editable Graphics/wp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wq.png -------------------------------------------------------------------------------- /Editable Graphics/wq.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Editable Graphics/wr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fulldecent/FDChessboardView/2d91c867150d13d91003475aad0515d55d4c4c95/Editable Graphics/wr.png -------------------------------------------------------------------------------- /Editable Graphics/wr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /FDChessboardView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'FDChessboardView' 3 | s.version = '3.0.0' 4 | s.license = 'MIT' 5 | s.summary = 'A view controller for chess boards' 6 | s.homepage = 'https://github.com/fulldecent/FDChessboardView' 7 | s.authors = { 'William Entriken' => 'github.com@phor.net' } 8 | s.source = { :git => 'https://github.com/fulldecent/FDChessboardView.git', :tag => s.version } 9 | s.ios.deployment_target = '8.0' 10 | s.source_files = 'Sources/**/*.swift' 11 | s.swift_version = '5.0' 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 William Entriken, Google LLC 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.1 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "FDChessboardView", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .library( 11 | name: "FDChessboardView", 12 | targets: ["FDChessboardView"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 21 | .target( 22 | name: "FDChessboardView", 23 | dependencies: []), 24 | .testTarget( 25 | name: "FDChessboardViewTests", 26 | dependencies: ["FDChessboardView"]), 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FDChessboardView 2 | ================ 3 | 4 | [![CI Status](http://img.shields.io/travis/fulldecent/FDChessboardView.svg?style=flat)](https://travis-ci.org/fulldecent/FDChessboardView) 5 | [![Version](https://img.shields.io/cocoapods/v/FDChessboardView.svg?style=flat)](http://cocoadocs.org/docsets/FDChessboardView) 6 | [![License](https://img.shields.io/cocoapods/l/FDChessboardView.svg?style=flat)](http://cocoadocs.org/docsets/FDChessboardView) 7 | [![Platform](https://img.shields.io/cocoapods/p/FDChessboardView.svg?style=flat)](http://cocoadocs.org/docsets/FDChessboardView) 8 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 9 | 10 | 11 | 12 | Features 13 | -------- 14 | 15 | * High resolution graphics 16 | * Customizable themes and game graphics 17 | * Supports all single board chess variants: suicide, losers, atomic, etc. 18 | * Supports games with odd piece arrangement and non-standard castling (Fisher 960) 19 | * Very clean API, this is just a view 20 | * Supports a minimum deployment target of iOS 8 or OS X Mavericks (10.9) 21 | 22 | ## Installation 23 | 24 | Add FDChessboardView to your project using Swift Package Manager. In Xcode that is simply: File > Swift Packages > Add Package Dependency... and you're done. Alternative installations options are shown below for legacy projects. 25 | 26 | ### CocoaPods 27 | 28 | If you are already using [CocoaPods](http://cocoapods.org), just add 'FDChessboardView' to your `Podfile` then run `pod install`. 29 | 30 | ### Carthage 31 | 32 | If you are already using [Carthage](https://github.com/Carthage/Carthage), just add to your `Cartfile`: 33 | 34 | ```ogdl 35 | github "fulldecent/FDChessboardView" ~> 0.1 36 | ``` 37 | 38 | Then run `carthage update` to build the framework and drag the built FDChessboardView.framework into your Xcode project. 39 | 40 | 41 | Usage 42 | ----- 43 | 44 | Import the project and implement a data source: 45 | 46 | ```swift 47 | import FDChessboardView 48 | 49 | public protocol FDChessboardViewDataSource: class { 50 | /// What piece is on the square? 51 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece? 52 | 53 | /// The last move 54 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)? 55 | 56 | /// The premove 57 | func chessboardViewPremove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)? 58 | } 59 | ``` 60 | 61 | If your application will allow the pieces to be moved, implement a delegate: 62 | 63 | ```swift 64 | public protocol FDChessboardViewDelegate: class { 65 | /// Where can this piece move to? 66 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare] 67 | 68 | /// Before a move happenes 69 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool 70 | 71 | /// After a move happened 72 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) 73 | } 74 | ``` 75 | 76 | Then you can customize the view or call certain actions: 77 | 78 | ```swift 79 | /// The location of a square on a chess board 80 | public struct FDChessboardSquare: Hashable { 81 | /// From 0...7 (a...h) 82 | public let file: Int 83 | 84 | /// From 0...7 (white king starting position to black king starting position) 85 | public let rank: Int 86 | } 87 | 88 | /// The pieces on a chess board 89 | public enum FDChessboardPiece: String { 90 | case WhitePawn 91 | case BlackPawn 92 | case WhiteKnight 93 | case BlackKnight 94 | case WhiteBishop 95 | case BlackBishop 96 | case WhiteRook 97 | case BlackRook 98 | case WhiteQueen 99 | case BlackQueen 100 | case WhiteKing 101 | case BlackKing 102 | } 103 | 104 | /// Display for a chess board 105 | @IBDesignable open class FDChessboardView: UIView { 106 | @IBInspectable open var lightBackgroundColor: UIColor 107 | @IBInspectable open var darkBackgroundColor: UIColor 108 | open var targetBackgroundColor: UIColor 109 | open var legalBackgroundColor: UIColor 110 | open var lastMoveColor: UIColor 111 | open var premoveColor: UIColor 112 | open weak var dataSource: FDChessboardViewDataSource? 113 | open weak var delegate: FDChessboardViewDelegate? 114 | open var doesAnimate: Bool 115 | open var doesShowLegalSquares: Bool 116 | open var doesShowLastMove: Bool 117 | open var doesShowPremove: Bool 118 | 119 | /// Add a piece onto the board 120 | open func setPiece(_ piece: FDChessboardPiece?, forSquare square: FDChessboardSquare) 121 | 122 | /// Repull all board information from data source 123 | open func reloadData() 124 | 125 | /// Move a piece on the board, clears any prior premove 126 | open func move(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) 127 | 128 | /// Premove a piece on the board, clears any prior premove 129 | open func premove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) 130 | 131 | /// Removes any premove on the board 132 | open func clearPremove() 133 | 134 | /// Move a piece on the board, clears any prior premove 135 | open func unmove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?, capturing: FDChessboardPiece) 136 | } 137 | ``` 138 | 139 | Upcoming features 140 | ----------------- 141 | 142 | These following items are in the API for discussion and awaiting implementation: 143 | 144 | * Display for last move 145 | * Mutable game state (i.e. can move the pieces) 146 | * Animation for piece moves 147 | * Highlighting of legal squares for a piece after begin dragging 148 | * Premove 149 | 150 | 151 | See also 152 | ----------- 153 | 154 | See also Kibitz for Mac which is making a comeback https://github.com/fulldecent/kibitz 155 | 156 | 157 | ## License 158 | 159 | FDChessboardView is available under the MIT license. See [the LICENSE file](LICENSE) for more information. 160 | -------------------------------------------------------------------------------- /Sources/FDChessboardView/FDChessboardImageData.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Encoded the images Base 64 using https://www.base64-image.de 4 | 5 | public enum FDChessboardImageB64: String { 6 | /// A white pawn 7 | case WhitePawn = "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" 8 | 9 | /// A black pawn 10 | case BlackPawn = "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" 11 | 12 | /// A white knight 13 | case WhiteKnight = "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" 14 | 15 | /// A black knight 16 | case BlackKnight = "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" 17 | 18 | /// A white bishop 19 | case WhiteBishop = "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" 20 | 21 | /// A black bishop 22 | case BlackBishop = "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" 23 | 24 | /// A white rook 25 | case WhiteRook = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAAE20lEQVR4Ae3YQ4BkVxyF8TM2aia27aTSu3AT27Y2se3hKjY3YW9i27ZtG60TozA179V9wX33+539dPf8v6IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJGmsKjk2Wu0ZqUqbG6n2jFYlx8YqQYN0lN6Tc+4N7aP+ymMHPS8H7HntoDz6ax+9IefcezpKg5SQfuqU29yZyu5IuYAdqezOlNtcp/opGevKAetQNnOrSy5gXZpb2XTIAVtXyThbDtjxymZ3uaDtrmyOlwN2tpLRKQfsTGVzhFzQjgh/AciwThWKAI6UC9qRBBCMAJqPAAiAAGb0hBYbVlgAx3lChh1XWADDWv6cGQngjy3iViqFBfCNs/imsAAqbmWRdgIgAAIggFd1eaY9U1gAz2T8ia/+MwEQQMACAghbeAAEQAAEQAAEMN4qaN85i++sgjaeAIoIYDmrkM3krGayCtlyBFBEAFOtQravs9rXKmRTCaCIALq8phW8qr9yVl+5agVvTXcRQBEB2D0+y6t7Ac/X1hb1yp7s753H957slT1fm1vcq/ss99hZAyCAVBAAARAAARAAARAAARAAARAAARAAARDAWO+W4MYSAEs1gDvkhrE7lIyP5Yaxj5WMz+WGsc+VjCfkhrEnlIy95IaxvZSQR2RWs0eUlH66QW62Ya6UeMOs5rtV/ZWYfjpVbrYTXFZTrOY7p/b8JMD5SYDzkwDnJwHOTwKcnwQ4PwkkcH4SOENutu19cKTb3mq+M9RP2ZFA/As8Py8E0Y4nfxLg/AEvBONc/XUdXiuydbj668YV8eTPs8BMjs1MPPqDEni+dAG8mOf8uKB0AVwgEAAIAAQAAgABgABAACAAEAAIAAQAAgABgABAACVEACAAEAAIAAQAAgABgABAACAAEAAIAAQAAgABgADKhwBAACAAEAAIAAQAAgABgABAACAAEAAIAAQAAgABlA4BgABAACAAEAAIAAQAAgABgABAACAAEAAIAAQAAqhBACM9NbKNJIDQAKJfQAC4VC7ZLlUOeFou2Z4WMltUvfLfN9jLR7bBVu16taiQ0a1y7ZZwbJaw6nerkMnmcv0OcmwOshq3uTBdI/WOXLuKP3ZsPnbFqt87GilMxyS5fqc7RqdZjZsotLSYuuTaLecex6jXK1r169aSQp63f/19n2P1kPtb9btT/YRp2EKu386O2U68FQx9+/eRY/aJx1v1e1+jhfC3f7wVLJN5tam65drN6Qf9SOR70HM2eyu4qeYVflfV43KCe1xVCYvraznRfa3FCeBqOeFdTQBfyAnvCwJw4kscASSOAFJHADUIoOp9S7zq9AIggENcZocQAAEQAAEQAAEQAAEQAAEQAAEkjgASRwCJI4DEEUDiCCBxBJCA2bWzDp7mXLtVPKHEW8Wq38HT3M6aXSVwkLrktsa6dJAit40cNLaNovacHDT2nCI2TA4eG6ZoVeTgsUr8ATACYATACOBof9Z0H/m1xPaRP2u6o8sdwASjtQkEkBACAAGAAEAAIAAkEMBGPqvl2EZ8E8gIgBEAI4DoRwAD1CWzoHVpgCJ2rcyCdq2itoS+klnb+0pLKHJL6Q71ySz3+nSHllIpjNF8LPfGCAAAAAAAAAAAAAAAAAAAAAAAAAAAAPi7nwAD4Sxds5lR+AAAAABJRU5ErkJggg==" 26 | 27 | /// A black rook 28 | case BlackRook = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAAEoElEQVR4AezBsQEAEBAEsOsB+y9rBt9Kki8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvn4UxNzynuqZk5t317CJAkjaIofEtj27Zt7ca2bdv2LMe2bds2NmNb7ayOvG0jIipyE/87391X6ixeqcSmU0BdOk0/yyX3rY5Qu8rYQ1/IFfaF9lAZ7TpC38ol97NOU5cCadMDcg93pYo7VW7BTlVxV8o93ANqUxibyhW2qoqZVw25BWtoXhWzqlxhmyqMq+UKO1vF7C+3aPurmLPlCrtaYTwgV9iVKuYUuUU7RcVcKVfYA2opAjhVbtFOJQACIAACIAACIAACIIDqCIAAKuwr3V1on8ot2qcFH/ErueAIgBEAIwBGAIwAGAEwAgg2AmAEwAiAEQAjAEYALGYAjAAYATACYNECmMxLe0WzpT1ZuACelDfwnx4Gf3oDy3pSYXwxtf81RvnXU1tfKIwf1jTGtKb1g8L4cE5nxiiZ57Q+VBgHyecao5xrWQcpkHfkdXyMj2c+xutY1jsK5jY1ZTZ0Td2mgDbUfzJTL22hoJbWN3Lw/aAVFNhMelEOvNc1q4KbVDfIQXeHJhckHa4s4OF3hjDSZuoV7PDbTBjDMvpWDrJvtYyQdxDO7Ufc23XX24947vKHHwdhm99zKt5zW+HDD8crk+WFnZKFrSHLdLxQ7CeEs7vpVDQ9e6mf+GFp9ZJvcSpusazeWkGF4Q6504f7QT9T8z3ow91pWXeqBNwgJ7YbBAIAAYAAQAAgABAACAAEAAIAAYAAQAAgABAACCA9BAACAAGAAEAAIAAQAAgABAACAAGAAEAAIAAQAAggPQQAAgABgABAACAAEAAIAAQAAgABBEAAIAAQAAgABAACAAGAAEAAIIAACAAEAAIAAYAAQAAgABAACAAEAAIAAYAAQAAgANwqL+gX3O266/YLXtCyblUJ+KTNnzgVn7jN+kQobHFlizoli1qZFhcKek6e1ZlTkXlWy3pJbUIBO8hDdrVTcbU1bNsrF6bSj/KQtXtv3+K7a75bvLfbrWH7RdMoBy6SE96FysH515ATXoNTMPf8S3ucgjnnX4BxCuacf0mPUzDn/FvFl/juRHeJV+EUnID5ta265Y080Ckb6I0sq1vban5huJX1gTxsrzh1r1gj9oFWlrCkeskj9rlT97k1ar20JAHcL4/aBU7dBdbou58A/pVHbTJf5X5OVT9f5cms0fcvAXjstXv6RNdujTsCCL7gCCA4AgiOAIIjgOAIIDgCCI4AgiOA4AggOAIIjgCCI4DgCCA4AgiPAAhgPT/vr4Ltea8XJoA5tbeOn+C8uPs7ov5e3LKOn+D21pxKwHF5/+55lqM6K/9fSY9Tze0i5+00R3Walb9dVGufy3mb3/87ov89v5W/z1Vjk8tFtpzv9LvBdqeXs4ptctXW9DKrvOlTDIARACMARgCMABgBMAJgBMAIgBEAIwBGAIwAGAEwAmAEQAB11aGGzCqtoQ7V2GMyq7THVGtL6X+5x2P/aynV3DJ6UU2ZlV5TL2oZJWFaLcBKb1oBAAAAAAAAAAAAAAAAAAAAAAAAAAAAoxsEnFqx8PjbQa0AAAAASUVORK5CYII=" 29 | 30 | /// A white queen 31 | case WhiteQueen = "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" 32 | 33 | /// A black queen 34 | case BlackQueen = "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" 35 | 36 | /// A white king 37 | case WhiteKing = "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" 38 | 39 | /// A black king 40 | case BlackKing = "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" 41 | } 42 | -------------------------------------------------------------------------------- /Sources/FDChessboardView/FDChessboardPiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FDChessboardPiece.swift 3 | // FDChessboardView 4 | // 5 | // Created by William Entriken on 2019-10-27. 6 | // Copyright © 2019 William Entriken. All rights reserved. 7 | // 8 | 9 | /// The pieces on a chess board 10 | public enum FDChessboardPiece: String { 11 | /// A white pawn 12 | case WhitePawn 13 | 14 | /// A black pawn 15 | case BlackPawn 16 | 17 | /// A white knight 18 | case WhiteKnight 19 | 20 | /// A black knight 21 | case BlackKnight 22 | 23 | /// A white bishop 24 | case WhiteBishop 25 | 26 | /// A black bishop 27 | case BlackBishop 28 | 29 | /// A white rook 30 | case WhiteRook 31 | 32 | /// A black rook 33 | case BlackRook 34 | 35 | /// A white queen 36 | case WhiteQueen 37 | 38 | /// A black queen 39 | case BlackQueen 40 | 41 | /// A white king 42 | case WhiteKing 43 | 44 | /// A black king 45 | case BlackKing 46 | 47 | public init?(fromCharacter character: Character) { 48 | switch character { 49 | case "K": 50 | self = .WhiteKing 51 | case "k": 52 | self = .BlackKing 53 | case "Q": 54 | self = .WhiteQueen 55 | case "q": 56 | self = .BlackQueen 57 | case "R": 58 | self = .WhiteRook 59 | case "r": 60 | self = .BlackRook 61 | case "B": 62 | self = .WhiteBishop 63 | case "b": 64 | self = .BlackBishop 65 | case "N": 66 | self = .WhiteKnight 67 | case "n": 68 | self = .BlackKnight 69 | case "P": 70 | self = .WhitePawn 71 | case "p": 72 | self = .BlackPawn 73 | default: 74 | return nil 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/FDChessboardView/FDChessboardView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FDChessboardView.swift 3 | // FDChessboardView 4 | // 5 | // Created by William Entriken on 2/2/16. 6 | // Copyright © 2016 William Entriken. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /// The location of a square on a chess board 13 | public struct FDChessboardSquare: Hashable { 14 | /// From 0...63 15 | public let index: Int 16 | 17 | /// From 0...7 (a...h) 18 | public let file: Int 19 | 20 | /// From 0...7 (white king starting position to black king starting position) 21 | public let rank: Int 22 | 23 | /// Like a4 24 | public let algebraic: String 25 | 26 | public init(index newIndex: Int) { 27 | index = newIndex 28 | file = newIndex % 8 29 | rank = newIndex / 8 30 | algebraic = ["a","b","c","d","e","f","g","h"][file] + String(rank + 1) 31 | } 32 | 33 | public init(newRank: Int, newFile: Int) { 34 | rank = newRank 35 | file = newFile 36 | index = newRank * 8 + newFile 37 | algebraic = ["a","b","c","d","e","f","g","h"][file] + String(rank + 1) 38 | } 39 | } 40 | 41 | public protocol FDChessboardViewDataSource: class { 42 | /// What piece is on the square? 43 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece? 44 | 45 | /// The last move 46 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)? 47 | 48 | /// The premove 49 | func chessboardViewPremove(_ board: FDChessboardView) -> (from:FDChessboardSquare, to:FDChessboardSquare)? 50 | } 51 | 52 | public protocol FDChessboardViewDelegate: class { 53 | /// Where can this piece move to? 54 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare] 55 | 56 | /// Before a move happenes 57 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool 58 | 59 | /// After a move happened 60 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) 61 | } 62 | 63 | /// Display for a chess board 64 | @IBDesignable open class FDChessboardView: UIView { 65 | /// Color for "white" board squares 66 | @IBInspectable open var lightBackgroundColor: UIColor = UIColor(red: 222.0/255, green:196.0/255, blue:160.0/255, alpha:1) 67 | 68 | /// Color for "black" board squares 69 | @IBInspectable open var darkBackgroundColor: UIColor = UIColor(red: 160.0/255, green:120.0/255, blue:55.0/255, alpha:1) 70 | 71 | /// Color for where a piece is moving to 72 | open var targetBackgroundColor = UIColor(hue: 0.75, saturation:0.5, brightness:0.5, alpha:1.0) 73 | 74 | /// Color for a legal square target 75 | open var legalBackgroundColor = UIColor(hue: 0.25, saturation:0.5, brightness:0.5, alpha:1.0) 76 | 77 | /// Color for the last move square 78 | open var lastMoveColor = UIColor(hue: 0.35, saturation:0.5, brightness:0.5, alpha:1.0) 79 | 80 | /// Color for a premove square 81 | open var premoveColor = UIColor(hue: 0.15, saturation:0.5, brightness:0.5, alpha:1.0) 82 | 83 | /// Datasource to say which pieces are on each square 84 | open weak var dataSource: FDChessboardViewDataSource? = nil { 85 | didSet { 86 | reloadData() 87 | } 88 | } 89 | 90 | /// Handler for user interaction with the view 91 | open weak var delegate: FDChessboardViewDelegate? = nil 92 | 93 | /// Should piece moves be animated? 94 | open var doesAnimate: Bool = true 95 | 96 | /// Should legal squares be shown when a piece is selected? 97 | open var doesShowLegalSquares: Bool = true 98 | 99 | /// Should the last move be shown? 100 | open var doesShowLastMove: Bool = true 101 | 102 | /// Should premove be shown? 103 | open var doesShowPremove: Bool = true 104 | 105 | private lazy var tilesAtIndex = [UIView]() 106 | 107 | private var pieceImageViewAtIndex = [Int : UIImageView]() 108 | 109 | private var lastMoveArrow: UIView? = nil 110 | 111 | private var premoveArrow: UIView? = nil 112 | 113 | private var pieceImages = [FDChessboardPiece: UIImage]() 114 | 115 | /// UIView initializer 116 | public override init(frame: CGRect) { 117 | super.init(frame: frame) 118 | setup() 119 | setupPiecesGraphics() 120 | } 121 | 122 | /// UIView initializer 123 | required public init?(coder aDecoder: NSCoder) { 124 | super.init(coder: aDecoder) 125 | setup() 126 | setupPiecesGraphics() 127 | } 128 | 129 | private func setupPiecesGraphics() { 130 | pieceImages[.WhitePawn] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhitePawn.rawValue, 131 | options: NSData.Base64DecodingOptions())!) 132 | pieceImages[.BlackPawn] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackPawn.rawValue, 133 | options: NSData.Base64DecodingOptions())!) 134 | pieceImages[.WhiteKnight] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteKnight.rawValue, 135 | options: NSData.Base64DecodingOptions())!) 136 | pieceImages[.BlackKnight] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackKnight.rawValue, 137 | options: NSData.Base64DecodingOptions())!) 138 | pieceImages[.WhiteBishop] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteBishop.rawValue, 139 | options: NSData.Base64DecodingOptions())!) 140 | pieceImages[.BlackBishop] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackBishop.rawValue, 141 | options: NSData.Base64DecodingOptions())!) 142 | pieceImages[.WhiteRook] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteRook.rawValue, 143 | options: NSData.Base64DecodingOptions())!) 144 | pieceImages[.BlackRook] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackRook.rawValue, 145 | options: NSData.Base64DecodingOptions())!) 146 | pieceImages[.WhiteQueen] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteQueen.rawValue, 147 | options: NSData.Base64DecodingOptions())!) 148 | pieceImages[.BlackQueen] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackQueen.rawValue, 149 | options: NSData.Base64DecodingOptions())!) 150 | pieceImages[.WhiteKing] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.WhiteKing.rawValue, 151 | options: NSData.Base64DecodingOptions())!) 152 | pieceImages[.BlackKing] = UIImage(data: Data(base64Encoded: FDChessboardImageB64.BlackKing.rawValue, 153 | options: NSData.Base64DecodingOptions())!) 154 | } 155 | 156 | private func setup() { 157 | self.translatesAutoresizingMaskIntoConstraints = false 158 | 159 | for index in 0..<64 { 160 | let square = FDChessboardSquare(index: index) 161 | let tile = UIView() 162 | tile.backgroundColor = (index + index/8) % 2 == 0 ? darkBackgroundColor : lightBackgroundColor 163 | tile.translatesAutoresizingMaskIntoConstraints = false 164 | addSubview(tile) 165 | tilesAtIndex.append(tile) 166 | 167 | switch square.rank { 168 | case 0: 169 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0)) 170 | case 7: 171 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .top, multiplier: 1, constant: 0)) 172 | addConstraint(NSLayoutConstraint(item: tile, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0)) 173 | addConstraint(NSLayoutConstraint(item: tile, attribute: .height, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .height, multiplier: 1, constant: 0)) 174 | default: 175 | addConstraint(NSLayoutConstraint(item: tile, attribute: .bottom, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .top, multiplier: 1, constant: 0)) 176 | addConstraint(NSLayoutConstraint(item: tile, attribute: .height, relatedBy: .equal, toItem: tilesAtIndex[index - 8], attribute: .height, multiplier: 1, constant: 0)) 177 | } 178 | switch square.file { 179 | case 0: 180 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0)) 181 | case 7: 182 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .right, multiplier: 1, constant: 0)) 183 | addConstraint(NSLayoutConstraint(item: tile, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0)) 184 | addConstraint(NSLayoutConstraint(item: tile, attribute: .width, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .width, multiplier: 1, constant: 0)) 185 | default: 186 | addConstraint(NSLayoutConstraint(item: tile, attribute: .left, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .right, multiplier: 1, constant: 0)) 187 | addConstraint(NSLayoutConstraint(item: tile, attribute: .width, relatedBy: .equal, toItem: tilesAtIndex[index - 1], attribute: .width, multiplier: 1, constant: 0)) 188 | } 189 | } 190 | self.layoutIfNeeded() 191 | } 192 | 193 | /* 194 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 195 | { 196 | UITouch *touch = [touches anyObject]; 197 | CGPoint point = [touch locationInView:self]; 198 | NSInteger x = point.x*8/self.frame.size.width; 199 | NSInteger y = 8-point.y*8/self.frame.size.height; 200 | UIView *tile = self.tilesPerSquare[y*8+x]; 201 | tile.backgroundColor = self.targetBackgroundColor; 202 | } 203 | 204 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 205 | { 206 | UITouch *touch = [touches anyObject]; 207 | CGPoint point = [touch locationInView:self]; 208 | if (![self pointInside:point withEvent:event]) 209 | return; 210 | NSInteger x = point.x*8/self.frame.size.width; 211 | NSInteger y = 8-point.y*8/self.frame.size.height; 212 | UIView *tile = self.tilesPerSquare[y*8+x]; 213 | tile.backgroundColor = self.legalBackgroundColor; 214 | } 215 | */ 216 | 217 | /// Add a piece onto the board 218 | open func setPiece(_ piece: FDChessboardPiece?, forSquare square: FDChessboardSquare){ 219 | let index = square.index 220 | self.pieceImageViewAtIndex[index]?.removeFromSuperview() 221 | self.pieceImageViewAtIndex.removeValue(forKey: index) 222 | guard let piece = piece else { 223 | return 224 | } 225 | 226 | let pieceImageView: UIImageView 227 | pieceImageView = UIImageView(image: pieceImages[piece]) 228 | pieceImageView.translatesAutoresizingMaskIntoConstraints = false 229 | self.pieceImageViewAtIndex[index] = pieceImageView 230 | self.addSubview(pieceImageView) 231 | 232 | let squareOne = self.tilesAtIndex.first! 233 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .width, relatedBy: .equal, toItem: squareOne, attribute: .width, multiplier: 1, constant: 0)) 234 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .height, relatedBy: .equal, toItem: squareOne, attribute: .height, multiplier: 1, constant: 0)) 235 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .top, relatedBy: .equal, toItem: self.tilesAtIndex[index], attribute: .top, multiplier: 1, constant: 0)) 236 | self.addConstraint(NSLayoutConstraint(item: pieceImageView, attribute: .leading, relatedBy: .equal, toItem: self.tilesAtIndex[index], attribute: .leading, multiplier: 1, constant: 0)) 237 | self.layoutIfNeeded() 238 | } 239 | 240 | /// Repull all board information from data source 241 | open func reloadData() { 242 | for index in 0 ..< 64 { 243 | let square = FDChessboardSquare(index: index) 244 | let newPiece = dataSource?.chessboardView(self, pieceForSquare:square) 245 | setPiece(newPiece, forSquare: square) 246 | } 247 | self.layoutIfNeeded() 248 | } 249 | 250 | /// Move a piece on the board, clears any prior premove 251 | open func move(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) { 252 | ///TODO: implement 253 | } 254 | 255 | /// Premove a piece on the board, clears any prior premove 256 | open func premove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?) { 257 | ///TODO: implement 258 | } 259 | 260 | /// Removes any premove on the board 261 | open func clearPremove() { 262 | } 263 | 264 | /// Move a piece on the board, clears any prior premove 265 | open func unmove(_ piece: FDChessboardPiece, from: FDChessboardSquare, to: FDChessboardSquare, promotedTo promoted: FDChessboardPiece?, capturing: FDChessboardPiece) { 266 | ///TODO: implement 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /Tests/CheckCocoaPodsQualityIndexes.rb: -------------------------------------------------------------------------------- 1 | 404: Not Found 2 | -------------------------------------------------------------------------------- /Tests/FDChessboardViewTests/FDChessboardViewTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import FDChessboardView 3 | 4 | final class FDChessboardViewTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(5, 5) 10 | } 11 | 12 | static var allTests = [ 13 | ("testExample", testExample), 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Tests/FDChessboardViewTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(FDChessboardViewTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import FDChessboardViewTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += FDChessboardViewTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /iOS Example/Sources/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOS Example 4 | // 5 | // Created by William Entriken on Nov 4, 2019. 6 | // Copyright © 2019 William Entriken. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /iOS Example/Sources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /iOS Example/Sources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /iOS Example/Sources/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /iOS Example/Sources/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /iOS Example/Sources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /iOS Example/Sources/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // iOS Example 4 | // 5 | // Created by William Entriken on Nov 4, 2019. 6 | // Copyright © 2019 William Entriken. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /iOS Example/Sources/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // iOS Example 4 | // 5 | // Created by William Entriken on Nov 4, 2019. 6 | // Copyright © 2019 William Entriken. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import FDChessboardView 11 | 12 | class SimpleChessDataSource: FDChessboardViewDataSource { 13 | var board = [FDChessboardSquare: FDChessboardPiece?]() 14 | var lastMove: (from: FDChessboardSquare, to: FDChessboardSquare)? = nil 15 | var premove: (from: FDChessboardSquare, to: FDChessboardSquare)? = nil 16 | 17 | func loadFen(fenPosition: String) { 18 | var rank = 7 19 | var file = 0 20 | for letter in fenPosition { 21 | if let piece = FDChessboardPiece(fromCharacter: letter) { 22 | board[.init(newRank: rank, newFile: file)] = piece 23 | file = file + 1 24 | } else if CharacterSet.decimalDigits.contains(letter.unicodeScalars.first!) { 25 | file = file + Int(letter.unicodeScalars.first!.value) - 48 26 | } else if letter == "/" { 27 | rank = rank - 1 28 | file = 0 29 | } else if letter == " " { 30 | break 31 | } 32 | } 33 | } 34 | 35 | func chessboardView(_ board: FDChessboardView, pieceForSquare square: FDChessboardSquare) -> FDChessboardPiece? { 36 | return self.board[square] ?? nil 37 | } 38 | 39 | func chessboardViewLastMove(_ board: FDChessboardView) -> (from: FDChessboardSquare, to: FDChessboardSquare)? { 40 | return lastMove 41 | } 42 | 43 | func chessboardViewPremove(_ board: FDChessboardView) -> (from: FDChessboardSquare, to: FDChessboardSquare)? { 44 | return premove 45 | } 46 | 47 | } 48 | 49 | class SimpleChessDelegate: FDChessboardViewDelegate { 50 | var didMoveCallback: ((_ board: FDChessboardView, _ from: FDChessboardSquare, _ to: FDChessboardSquare, _ promotion: FDChessboardPiece?) -> ())? = nil 51 | 52 | func chessboardView(_ board: FDChessboardView, canMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) -> Bool { 53 | return true 54 | } 55 | 56 | func chessboardView(_ board: FDChessboardView, legalDestinationsForPieceAtSquare from: FDChessboardSquare) -> [FDChessboardSquare] { 57 | var retval = [FDChessboardSquare]() 58 | if from.file > 0 { 59 | retval.append(FDChessboardSquare(index: from.index - 8)) 60 | } 61 | if from.file < 8 { 62 | retval.append(FDChessboardSquare(index: from.index + 8)) 63 | } 64 | if from.rank > 0 { 65 | retval.append(FDChessboardSquare(index: from.index - 1)) 66 | } 67 | if from.rank < 8 { 68 | retval.append(FDChessboardSquare(index: from.index + 1)) 69 | } 70 | return retval 71 | } 72 | 73 | func chessboardView(_ board: FDChessboardView, didMoveFrom from: FDChessboardSquare, to: FDChessboardSquare, withPromotion promotion: FDChessboardPiece?) { 74 | if let callback = didMoveCallback { 75 | callback(board, from, to, promotion) 76 | } 77 | } 78 | } 79 | 80 | class ViewController: UIViewController { 81 | @IBOutlet var chessboard: FDChessboardView! 82 | 83 | let dataSource = SimpleChessDataSource() 84 | let delegate = SimpleChessDelegate() 85 | 86 | override func viewDidLoad() { 87 | super.viewDidLoad() 88 | dataSource.loadFen(fenPosition: "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2") 89 | chessboard.dataSource = dataSource 90 | chessboard.delegate = delegate 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /iOS Example/iOS Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D97695022370C0AE006BB437 /* FDChessboardView in Frameworks */ = {isa = PBXBuildFile; productRef = D97695012370C0AE006BB437 /* FDChessboardView */; }; 11 | D9A12776235699C600D136A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12775235699C600D136A5 /* AppDelegate.swift */; }; 12 | D9A12778235699C600D136A5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12777235699C600D136A5 /* SceneDelegate.swift */; }; 13 | D9A1277A235699C600D136A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A12779235699C600D136A5 /* ViewController.swift */; }; 14 | D9A1277D235699C600D136A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D9A1277B235699C600D136A5 /* Main.storyboard */; }; 15 | D9A1277F235699C700D136A5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D9A1277E235699C700D136A5 /* Assets.xcassets */; }; 16 | D9A12782235699C700D136A5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D9A12780235699C700D136A5 /* LaunchScreen.storyboard */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | D9A12772235699C600D136A5 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | D9A12775235699C600D136A5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | D9A12777235699C600D136A5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 23 | D9A12779235699C600D136A5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 24 | D9A1277C235699C600D136A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | D9A1277E235699C700D136A5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | D9A12781235699C700D136A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | D9A12783235699C700D136A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | D9A1276F235699C600D136A5 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | D97695022370C0AE006BB437 /* FDChessboardView in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | D9A12769235699C600D136A5 = { 43 | isa = PBXGroup; 44 | children = ( 45 | D9A12774235699C600D136A5 /* Sources */, 46 | D9A12773235699C600D136A5 /* Products */, 47 | D9A127892356A25E00D136A5 /* Frameworks */, 48 | ); 49 | sourceTree = ""; 50 | }; 51 | D9A12773235699C600D136A5 /* Products */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | D9A12772235699C600D136A5 /* iOS Example.app */, 55 | ); 56 | name = Products; 57 | sourceTree = ""; 58 | }; 59 | D9A12774235699C600D136A5 /* Sources */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | D9A12775235699C600D136A5 /* AppDelegate.swift */, 63 | D9A12777235699C600D136A5 /* SceneDelegate.swift */, 64 | D9A12779235699C600D136A5 /* ViewController.swift */, 65 | D9A1277B235699C600D136A5 /* Main.storyboard */, 66 | D9A1277E235699C700D136A5 /* Assets.xcassets */, 67 | D9A12780235699C700D136A5 /* LaunchScreen.storyboard */, 68 | D9A12783235699C700D136A5 /* Info.plist */, 69 | ); 70 | path = Sources; 71 | sourceTree = ""; 72 | }; 73 | D9A127892356A25E00D136A5 /* Frameworks */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | ); 77 | name = Frameworks; 78 | sourceTree = ""; 79 | }; 80 | /* End PBXGroup section */ 81 | 82 | /* Begin PBXNativeTarget section */ 83 | D9A12771235699C600D136A5 /* iOS Example */ = { 84 | isa = PBXNativeTarget; 85 | buildConfigurationList = D9A12786235699C700D136A5 /* Build configuration list for PBXNativeTarget "iOS Example" */; 86 | buildPhases = ( 87 | D9A1276E235699C600D136A5 /* Sources */, 88 | D9A1276F235699C600D136A5 /* Frameworks */, 89 | D9A12770235699C600D136A5 /* Resources */, 90 | ); 91 | buildRules = ( 92 | ); 93 | dependencies = ( 94 | ); 95 | name = "iOS Example"; 96 | packageProductDependencies = ( 97 | D97695012370C0AE006BB437 /* FDChessboardView */, 98 | ); 99 | productName = "iOS Example"; 100 | productReference = D9A12772235699C600D136A5 /* iOS Example.app */; 101 | productType = "com.apple.product-type.application"; 102 | }; 103 | /* End PBXNativeTarget section */ 104 | 105 | /* Begin PBXProject section */ 106 | D9A1276A235699C600D136A5 /* Project object */ = { 107 | isa = PBXProject; 108 | attributes = { 109 | LastSwiftUpdateCheck = 1110; 110 | LastUpgradeCheck = 1110; 111 | ORGANIZATIONNAME = "William Entriken"; 112 | TargetAttributes = { 113 | D9A12771235699C600D136A5 = { 114 | CreatedOnToolsVersion = 11.1; 115 | }; 116 | }; 117 | }; 118 | buildConfigurationList = D9A1276D235699C600D136A5 /* Build configuration list for PBXProject "iOS Example" */; 119 | compatibilityVersion = "Xcode 9.3"; 120 | developmentRegion = en; 121 | hasScannedForEncodings = 0; 122 | knownRegions = ( 123 | en, 124 | Base, 125 | ); 126 | mainGroup = D9A12769235699C600D136A5; 127 | productRefGroup = D9A12773235699C600D136A5 /* Products */; 128 | projectDirPath = ""; 129 | projectRoot = ""; 130 | targets = ( 131 | D9A12771235699C600D136A5 /* iOS Example */, 132 | ); 133 | }; 134 | /* End PBXProject section */ 135 | 136 | /* Begin PBXResourcesBuildPhase section */ 137 | D9A12770235699C600D136A5 /* Resources */ = { 138 | isa = PBXResourcesBuildPhase; 139 | buildActionMask = 2147483647; 140 | files = ( 141 | D9A12782235699C700D136A5 /* LaunchScreen.storyboard in Resources */, 142 | D9A1277F235699C700D136A5 /* Assets.xcassets in Resources */, 143 | D9A1277D235699C600D136A5 /* Main.storyboard in Resources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXResourcesBuildPhase section */ 148 | 149 | /* Begin PBXSourcesBuildPhase section */ 150 | D9A1276E235699C600D136A5 /* Sources */ = { 151 | isa = PBXSourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | D9A1277A235699C600D136A5 /* ViewController.swift in Sources */, 155 | D9A12776235699C600D136A5 /* AppDelegate.swift in Sources */, 156 | D9A12778235699C600D136A5 /* SceneDelegate.swift in Sources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXSourcesBuildPhase section */ 161 | 162 | /* Begin PBXVariantGroup section */ 163 | D9A1277B235699C600D136A5 /* Main.storyboard */ = { 164 | isa = PBXVariantGroup; 165 | children = ( 166 | D9A1277C235699C600D136A5 /* Base */, 167 | ); 168 | name = Main.storyboard; 169 | sourceTree = ""; 170 | }; 171 | D9A12780235699C700D136A5 /* LaunchScreen.storyboard */ = { 172 | isa = PBXVariantGroup; 173 | children = ( 174 | D9A12781235699C700D136A5 /* Base */, 175 | ); 176 | name = LaunchScreen.storyboard; 177 | sourceTree = ""; 178 | }; 179 | /* End PBXVariantGroup section */ 180 | 181 | /* Begin XCBuildConfiguration section */ 182 | D9A12784235699C700D136A5 /* Debug */ = { 183 | isa = XCBuildConfiguration; 184 | buildSettings = { 185 | ALWAYS_SEARCH_USER_PATHS = NO; 186 | CLANG_ANALYZER_NONNULL = YES; 187 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 189 | CLANG_CXX_LIBRARY = "libc++"; 190 | CLANG_ENABLE_MODULES = YES; 191 | CLANG_ENABLE_OBJC_ARC = YES; 192 | CLANG_ENABLE_OBJC_WEAK = YES; 193 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 194 | CLANG_WARN_BOOL_CONVERSION = YES; 195 | CLANG_WARN_COMMA = YES; 196 | CLANG_WARN_CONSTANT_CONVERSION = YES; 197 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 206 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 208 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 209 | CLANG_WARN_STRICT_PROTOTYPES = YES; 210 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 211 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 212 | CLANG_WARN_UNREACHABLE_CODE = YES; 213 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 214 | COPY_PHASE_STRIP = NO; 215 | DEBUG_INFORMATION_FORMAT = dwarf; 216 | ENABLE_STRICT_OBJC_MSGSEND = YES; 217 | ENABLE_TESTABILITY = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu11; 219 | GCC_DYNAMIC_NO_PIC = NO; 220 | GCC_NO_COMMON_BLOCKS = YES; 221 | GCC_OPTIMIZATION_LEVEL = 0; 222 | GCC_PREPROCESSOR_DEFINITIONS = ( 223 | "DEBUG=1", 224 | "$(inherited)", 225 | ); 226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 228 | GCC_WARN_UNDECLARED_SELECTOR = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 230 | GCC_WARN_UNUSED_FUNCTION = YES; 231 | GCC_WARN_UNUSED_VARIABLE = YES; 232 | IPHONEOS_DEPLOYMENT_TARGET = 13.1; 233 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 234 | MTL_FAST_MATH = YES; 235 | ONLY_ACTIVE_ARCH = YES; 236 | SDKROOT = iphoneos; 237 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 238 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 239 | }; 240 | name = Debug; 241 | }; 242 | D9A12785235699C700D136A5 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_ANALYZER_NONNULL = YES; 247 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_ENABLE_OBJC_WEAK = YES; 253 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 254 | CLANG_WARN_BOOL_CONVERSION = YES; 255 | CLANG_WARN_COMMA = YES; 256 | CLANG_WARN_CONSTANT_CONVERSION = YES; 257 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 258 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 259 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 260 | CLANG_WARN_EMPTY_BODY = YES; 261 | CLANG_WARN_ENUM_CONVERSION = YES; 262 | CLANG_WARN_INFINITE_RECURSION = YES; 263 | CLANG_WARN_INT_CONVERSION = YES; 264 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 266 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 268 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 269 | CLANG_WARN_STRICT_PROTOTYPES = YES; 270 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 271 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 272 | CLANG_WARN_UNREACHABLE_CODE = YES; 273 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 276 | ENABLE_NS_ASSERTIONS = NO; 277 | ENABLE_STRICT_OBJC_MSGSEND = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu11; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 13.1; 287 | MTL_ENABLE_DEBUG_INFO = NO; 288 | MTL_FAST_MATH = YES; 289 | SDKROOT = iphoneos; 290 | SWIFT_COMPILATION_MODE = wholemodule; 291 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 292 | VALIDATE_PRODUCT = YES; 293 | }; 294 | name = Release; 295 | }; 296 | D9A12787235699C700D136A5 /* Debug */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CODE_SIGN_STYLE = Automatic; 301 | INFOPLIST_FILE = Sources/Info.plist; 302 | LD_RUNPATH_SEARCH_PATHS = ( 303 | "$(inherited)", 304 | "@executable_path/Frameworks", 305 | ); 306 | PRODUCT_BUNDLE_IDENTIFIER = "net.phor.iOS-Example"; 307 | PRODUCT_NAME = "$(TARGET_NAME)"; 308 | SWIFT_VERSION = 5.0; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | }; 311 | name = Debug; 312 | }; 313 | D9A12788235699C700D136A5 /* Release */ = { 314 | isa = XCBuildConfiguration; 315 | buildSettings = { 316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 317 | CODE_SIGN_STYLE = Automatic; 318 | INFOPLIST_FILE = Sources/Info.plist; 319 | LD_RUNPATH_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "@executable_path/Frameworks", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = "net.phor.iOS-Example"; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_VERSION = 5.0; 326 | TARGETED_DEVICE_FAMILY = "1,2"; 327 | }; 328 | name = Release; 329 | }; 330 | /* End XCBuildConfiguration section */ 331 | 332 | /* Begin XCConfigurationList section */ 333 | D9A1276D235699C600D136A5 /* Build configuration list for PBXProject "iOS Example" */ = { 334 | isa = XCConfigurationList; 335 | buildConfigurations = ( 336 | D9A12784235699C700D136A5 /* Debug */, 337 | D9A12785235699C700D136A5 /* Release */, 338 | ); 339 | defaultConfigurationIsVisible = 0; 340 | defaultConfigurationName = Release; 341 | }; 342 | D9A12786235699C700D136A5 /* Build configuration list for PBXNativeTarget "iOS Example" */ = { 343 | isa = XCConfigurationList; 344 | buildConfigurations = ( 345 | D9A12787235699C700D136A5 /* Debug */, 346 | D9A12788235699C700D136A5 /* Release */, 347 | ); 348 | defaultConfigurationIsVisible = 0; 349 | defaultConfigurationName = Release; 350 | }; 351 | /* End XCConfigurationList section */ 352 | 353 | /* Begin XCSwiftPackageProductDependency section */ 354 | D97695012370C0AE006BB437 /* FDChessboardView */ = { 355 | isa = XCSwiftPackageProductDependency; 356 | productName = FDChessboardView; 357 | }; 358 | /* End XCSwiftPackageProductDependency section */ 359 | }; 360 | rootObject = D9A1276A235699C600D136A5 /* Project object */; 361 | } 362 | -------------------------------------------------------------------------------- /iOS Example/iOS Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS Example/iOS Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOS Example/iOS Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /iOS Example/iOS Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------