├── AppKit Cocoa Resizable NSView ├── Assets.xcassets │ ├── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── main.swift ├── AppKit_Cocoa_Resizable_NSView.entitlements ├── AppDelegate.swift ├── Info.plist ├── ViewController.swift ├── NSViewHelpers.swift ├── ResizableView.swift └── DraggableResizableView.swift ├── Screenshots └── BBDragResizableView.gif ├── AppKit Cocoa Resizable NSView.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── fingent.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── README.md └── .gitignore /AppKit Cocoa Resizable NSView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Screenshots/BBDragResizableView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bibinjacobpulickal/BBDragResizableView/HEAD/Screenshots/BBDragResizableView.gif -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // CocoaTest 4 | // 5 | // Created by Bibin Jacob Pulickal on 21/05/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | let appDelegate = AppDelegate() 12 | NSApplication.shared.delegate = appDelegate 13 | NSApplication.shared.run() 14 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/AppKit_Cocoa_Resizable_NSView.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView.xcodeproj/xcuserdata/fingent.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppKit Cocoa Resizable NSView.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BBDragResizableView 2 | A sample project to show how to create a draggable and resizable NSView in Cocoa framework in AppKit using Xcode 11.4 on MacOS 10.15 using Swift 5.2 3 | 4 | --- 5 | ![Platform](https://img.shields.io/badge/platform-MacOS-blue.svg?style=flat) 6 | [![MacOS](https://img.shields.io/badge/MacOS-10.15-green.svg?style=flat)](https://www.apple.com/in/macos/catalina/) 7 | [![Xcode](https://img.shields.io/badge/XCode-11.4-blue.svg)](https://developer.apple.com/xcode/) 8 | [![Swift](https://img.shields.io/badge/Swift-5.2-orange.svg?style=flat)](https://developer.apple.com/swift/) 9 | 10 | ## Working Example 11 | 12 | 13 | ## Example 14 | Download the project. 15 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CocoaTest 4 | // 5 | // Created by Bibin Jacob Pulickal on 21/05/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class AppDelegate: NSObject, NSApplicationDelegate { 12 | 13 | var window: NSWindow? 14 | 15 | func applicationDidFinishLaunching(_ aNotification: Notification) { 16 | window = NSWindow(contentViewController: ViewController()) 17 | window?.makeKeyAndOrderFront(nil) 18 | setupWindowProperties() 19 | } 20 | 21 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true } 22 | 23 | func setupWindowProperties() { 24 | window?.toolbar?.showsBaselineSeparator = false 25 | window?.titlebarAppearsTransparent = true 26 | window?.titleVisibility = .hidden 27 | window?.styleMask.insert(.fullSizeContentView) 28 | window?.center() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/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 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AppKit Cocoa Resizable NSView 4 | // 5 | // Created by Bibin Jacob Pulickal on 06/06/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import AutoLayoutProxy 11 | 12 | class ViewController: NSViewController { 13 | 14 | private let draggableResizableView = DraggableResizableView() 15 | 16 | override func loadView() { 17 | view = NSView() 18 | view.size >= 500 19 | view.addSubview(NSButton(title: "RESET", target: self, action: #selector(resetFrame))) { 20 | $0.centerX == $1.centerX 21 | } 22 | view.addSubview(draggableResizableView) 23 | } 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | perform(#selector(resetFrame), with: nil, afterDelay: 1) 28 | } 29 | 30 | @objc func resetFrame() { 31 | let width = view.bounds.width / 5 32 | let height = view.bounds.height / 5 33 | let x = (view.bounds.width - width) * 0.5 34 | let y = (view.bounds.height - height) * 0.5 35 | draggableResizableView.frame = CGRect(x: x, y: y, width: width, height: height) 36 | draggableResizableView.autoresizingMask = [.minXMargin, .minYMargin, .maxXMargin, .maxYMargin] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.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/ -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/NSViewHelpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSViewHelpers.swift 3 | // IncomingCallPopup 4 | // 5 | // Created by Bibin Jacob Pulickal on 10/05/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | #if canImport(Cocoa) 10 | import Cocoa 11 | 12 | // MARK: - Properties 13 | public extension NSView { 14 | 15 | @IBInspectable 16 | var backgroundColor: NSColor? { 17 | get { 18 | guard let color = layer?.backgroundColor else { return nil } 19 | return NSColor(cgColor: color) 20 | } 21 | set { 22 | wantsLayer = true 23 | layer?.backgroundColor = newValue?.cgColor 24 | } 25 | } 26 | 27 | var origin: CGPoint { 28 | get { 29 | frame.origin 30 | } 31 | set { 32 | frame.origin.x = newValue.x 33 | frame.origin.y = newValue.y 34 | } 35 | } 36 | 37 | var size: CGSize { 38 | get { 39 | frame.size 40 | } 41 | set { 42 | width = newValue.width 43 | height = newValue.height 44 | } 45 | } 46 | 47 | var width: CGFloat { 48 | get { 49 | frame.size.width 50 | } 51 | set { 52 | frame.size.width = newValue 53 | } 54 | } 55 | 56 | var height: CGFloat { 57 | get { 58 | frame.size.height 59 | } 60 | set { 61 | frame.size.height = newValue 62 | } 63 | } 64 | 65 | @IBInspectable 66 | var borderColor: NSColor? { 67 | get { 68 | guard let color = layer?.borderColor else { return nil } 69 | return NSColor(cgColor: color) 70 | } 71 | set { 72 | wantsLayer = true 73 | layer?.borderColor = newValue?.cgColor 74 | } 75 | } 76 | 77 | @IBInspectable 78 | var borderWidth: CGFloat { 79 | get { 80 | layer?.borderWidth ?? 0 81 | } 82 | set { 83 | wantsLayer = true 84 | layer?.borderWidth = newValue 85 | } 86 | } 87 | 88 | @IBInspectable 89 | var cornerRadius: CGFloat { 90 | get { 91 | layer?.cornerRadius ?? 0 92 | } 93 | set { 94 | wantsLayer = true 95 | layer?.masksToBounds = true 96 | layer?.cornerRadius = abs(CGFloat(Int(newValue * 100)) / 100) 97 | } 98 | } 99 | 100 | @IBInspectable 101 | var shadowColor: NSColor? { 102 | get { 103 | guard let color = layer?.shadowColor else { return nil } 104 | return NSColor(cgColor: color) 105 | } 106 | set { 107 | wantsLayer = true 108 | layer?.shadowColor = newValue?.cgColor 109 | } 110 | } 111 | 112 | @IBInspectable 113 | var shadowOffset: CGSize { 114 | get { 115 | layer?.shadowOffset ?? CGSize.zero 116 | } 117 | set { 118 | wantsLayer = true 119 | layer?.shadowOffset = newValue 120 | } 121 | } 122 | 123 | @IBInspectable 124 | var shadowOpacity: Float { 125 | get { 126 | layer?.shadowOpacity ?? 0 127 | } 128 | set { 129 | wantsLayer = true 130 | layer?.shadowOpacity = newValue 131 | } 132 | } 133 | 134 | @IBInspectable 135 | var shadowRadius: CGFloat { 136 | get { 137 | return layer?.shadowRadius ?? 0 138 | } 139 | set { 140 | wantsLayer = true 141 | layer?.shadowRadius = newValue 142 | } 143 | } 144 | 145 | func addTrackingRect(_ rect: NSRect) { 146 | addTrackingArea(NSTrackingArea( 147 | rect: rect, 148 | options: [ 149 | .mouseMoved, 150 | .mouseEnteredAndExited, 151 | .activeAlways], 152 | owner: self)) 153 | } 154 | } 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/ResizableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResizableView.swift 3 | // AppKit Cocoa Resizable NSView 4 | // 5 | // Created by Bibin Jacob Pulickal on 06/06/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class ResizableView: NSView { 12 | 13 | private let resizableArea = CGFloat(2) 14 | private var draggedPoint = CGPoint.zero 15 | 16 | override init(frame frameRect: NSRect) { 17 | super.init(frame: frameRect) 18 | backgroundColor = .red 19 | borderColor = .white 20 | borderWidth = resizableArea 21 | } 22 | 23 | override func updateTrackingAreas() { 24 | super.updateTrackingAreas() 25 | trackingAreas.forEach { area in 26 | removeTrackingArea(area) 27 | } 28 | addTrackingRect(bounds) 29 | } 30 | 31 | required init?(coder decoder: NSCoder) { 32 | fatalError("init(coder:) has not been implemented") 33 | } 34 | 35 | override func mouseExited(with event: NSEvent) { 36 | super.mouseExited(with: event) 37 | NSCursor.arrow.set() 38 | } 39 | 40 | override func mouseDown(with event: NSEvent) { 41 | super.mouseDown(with: event) 42 | let locationInView = convert(event.locationInWindow, from: nil) 43 | draggedPoint = locationInView 44 | } 45 | 46 | override func mouseUp(with event: NSEvent) { 47 | super.mouseUp(with: event) 48 | draggedPoint = .zero 49 | } 50 | 51 | override func mouseMoved(with event: NSEvent) { 52 | super.mouseMoved(with: event) 53 | let locationInView = convert(event.locationInWindow, from: nil) 54 | cursorBorderPosition(locationInView) 55 | } 56 | 57 | override func mouseDragged(with event: NSEvent) { 58 | super.mouseDragged(with: event) 59 | borderWidth = resizableArea 60 | let locationInView = convert(event.locationInWindow, from: nil) 61 | let horizontalDistanceDragged = locationInView.x - draggedPoint.x 62 | let verticalDistanceDragged = locationInView.y - draggedPoint.y 63 | let cursorPosition = cursorBorderPosition(draggedPoint) 64 | if cursorPosition != .none { 65 | let drag = CGPoint(x: horizontalDistanceDragged, y: verticalDistanceDragged) 66 | if checkIfBorder(cursorPosition, exceedsSuperviewBorderWithPadding: 12, andDraggedOutward: drag) { 67 | return 68 | } 69 | } 70 | switch cursorPosition { 71 | case .top: 72 | size.height += verticalDistanceDragged 73 | draggedPoint = locationInView 74 | case .left: 75 | origin.x += horizontalDistanceDragged 76 | size.width -= horizontalDistanceDragged 77 | case .bottom: 78 | origin.y += verticalDistanceDragged 79 | size.height -= verticalDistanceDragged 80 | case .right: 81 | size.width += horizontalDistanceDragged 82 | draggedPoint = locationInView 83 | case .none: 84 | break 85 | } 86 | } 87 | 88 | @discardableResult 89 | func cursorBorderPosition(_ locationInView: CGPoint) -> BorderPosition { 90 | if locationInView.x < resizableArea { 91 | NSCursor.resizeLeftRight.set() 92 | return .left 93 | } else if locationInView.x > bounds.width - resizableArea { 94 | NSCursor.resizeLeftRight.set() 95 | return .right 96 | } else if locationInView.y < resizableArea { 97 | NSCursor.resizeUpDown.set() 98 | return .bottom 99 | } else if locationInView.y > bounds.height - resizableArea { 100 | NSCursor.resizeUpDown.set() 101 | return .top 102 | } else { 103 | NSCursor.arrow.set() 104 | return .none 105 | } 106 | } 107 | 108 | private func checkIfBorder(_ border: BorderPosition, 109 | exceedsSuperviewBorderWithPadding padding: CGFloat, 110 | andDraggedOutward drag: CGPoint) -> Bool { 111 | if border == .left && frame.minX <= padding && drag.x < 0 { 112 | return true 113 | } 114 | if border == .bottom && frame.minY <= padding && drag.y < 0 { 115 | return true 116 | } 117 | guard let superView = superview else { return false } 118 | if border == .right && frame.maxX >= superView.frame.maxX - padding && drag.x > 0 { 119 | return true 120 | } 121 | if border == .top && frame.maxY >= superView.frame.maxY - padding && drag.y > 0 { 122 | return true 123 | } 124 | return false 125 | } 126 | 127 | enum BorderPosition { 128 | case top, left, bottom, right, none 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView/DraggableResizableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DraggableResizableView.swift 3 | // AppKit Cocoa Resizable NSView 4 | // 5 | // Created by Bibin Jacob Pulickal on 11/06/19. 6 | // Copyright © 2019 Bibin Jacob Pulickal. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class DraggableResizableView: NSView { 12 | 13 | private let resizableArea: CGFloat = 4 14 | private let borderPadding: CGFloat = 32 15 | private var draggedPoint: CGPoint = .zero 16 | 17 | override init(frame frameRect: NSRect) { 18 | super.init(frame: frameRect) 19 | backgroundColor = .red 20 | } 21 | 22 | override func updateTrackingAreas() { 23 | super.updateTrackingAreas() 24 | trackingAreas.forEach { area in 25 | removeTrackingArea(area) 26 | } 27 | addTrackingRect(bounds) 28 | } 29 | 30 | required init?(coder decoder: NSCoder) { 31 | fatalError("init(coder:) has not been implemented") 32 | } 33 | 34 | override func mouseEntered(with event: NSEvent) { 35 | super.mouseEntered(with: event) 36 | backgroundColor = .green 37 | borderColor = .white 38 | borderWidth = 1 39 | } 40 | 41 | override func mouseExited(with event: NSEvent) { 42 | super.mouseExited(with: event) 43 | NSCursor.arrow.set() 44 | backgroundColor = .red 45 | borderColor = .clear 46 | borderWidth = 0 47 | } 48 | 49 | override func mouseDown(with event: NSEvent) { 50 | super.mouseDown(with: event) 51 | let locationInView = convert(event.locationInWindow, from: nil) 52 | draggedPoint = locationInView 53 | } 54 | 55 | override func mouseUp(with event: NSEvent) { 56 | super.mouseUp(with: event) 57 | draggedPoint = .zero 58 | } 59 | 60 | override func mouseMoved(with event: NSEvent) { 61 | super.mouseMoved(with: event) 62 | let locationInView = convert(event.locationInWindow, from: nil) 63 | cursorBorderPosition(locationInView) 64 | } 65 | 66 | override func mouseDragged(with event: NSEvent) { 67 | super.mouseDragged(with: event) 68 | backgroundColor = .green 69 | borderWidth = 1 70 | let locationInView = convert(event.locationInWindow, from: nil) 71 | let horizontalDistanceDragged = locationInView.x - draggedPoint.x 72 | let verticalDistanceDragged = locationInView.y - draggedPoint.y 73 | let cursorPosition = cursorBorderPosition(draggedPoint) 74 | if cursorPosition != .none { 75 | let drag = CGPoint(x: horizontalDistanceDragged, y: verticalDistanceDragged) 76 | if checkIfBorder(cursorPosition, andDraggedOutward: drag) { 77 | return 78 | } 79 | } 80 | switch cursorPosition { 81 | case .top: 82 | size.height += verticalDistanceDragged 83 | draggedPoint = locationInView 84 | case .left: 85 | origin.x += horizontalDistanceDragged 86 | size.width -= horizontalDistanceDragged 87 | case .bottom: 88 | origin.y += verticalDistanceDragged 89 | size.height -= verticalDistanceDragged 90 | case .right: 91 | size.width += horizontalDistanceDragged 92 | draggedPoint = locationInView 93 | case .none: 94 | origin.x += locationInView.x - draggedPoint.x 95 | origin.y += locationInView.y - draggedPoint.y 96 | repositionView() 97 | } 98 | } 99 | 100 | @discardableResult 101 | func cursorBorderPosition(_ locationInView: CGPoint) -> BorderPosition { 102 | if locationInView.x < resizableArea { 103 | NSCursor.resizeLeftRight.set() 104 | return .left 105 | } else if locationInView.x > bounds.width - resizableArea { 106 | NSCursor.resizeLeftRight.set() 107 | return .right 108 | } else if locationInView.y < resizableArea { 109 | NSCursor.resizeUpDown.set() 110 | return .bottom 111 | } else if locationInView.y > bounds.height - resizableArea { 112 | NSCursor.resizeUpDown.set() 113 | return .top 114 | } else { 115 | NSCursor.arrow.set() 116 | return .none 117 | } 118 | } 119 | 120 | enum BorderPosition { 121 | case top, left, bottom, right, none 122 | } 123 | 124 | private func checkIfBorder(_ border: BorderPosition, 125 | andDraggedOutward drag: CGPoint) -> Bool { 126 | if border == .left && frame.minX <= borderPadding && drag.x < 0 { 127 | return true 128 | } 129 | if border == .bottom && frame.minY <= borderPadding && drag.y < 0 { 130 | return true 131 | } 132 | guard let superView = superview else { return false } 133 | if border == .right && frame.maxX >= superView.frame.maxX - borderPadding && drag.x > 0 { 134 | return true 135 | } 136 | if border == .top && frame.maxY >= superView.frame.maxY - borderPadding && drag.y > 0 { 137 | return true 138 | } 139 | return false 140 | } 141 | 142 | private func repositionView() { 143 | if frame.minX < borderPadding { 144 | origin.x = borderPadding 145 | } 146 | if frame.minY < borderPadding { 147 | origin.y = borderPadding 148 | } 149 | guard let superView = superview else { return } 150 | if frame.maxX > superView.frame.maxX - borderPadding { 151 | origin.x = superView.frame.maxX - frame.width - borderPadding 152 | } 153 | if frame.maxY > superView.frame.maxY - borderPadding { 154 | origin.y = superView.frame.maxY - frame.height - borderPadding 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /AppKit Cocoa Resizable NSView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AD2713E922A94A72004A042C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AD2713E822A94A72004A042C /* Assets.xcassets */; }; 11 | AD2713F922A94AB0004A042C /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD2713F522A94AAF004A042C /* main.swift */; }; 12 | AD2713FA22A94AB0004A042C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD2713F622A94AAF004A042C /* AppDelegate.swift */; }; 13 | AD2713FB22A94AB0004A042C /* NSViewHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD2713F722A94AAF004A042C /* NSViewHelpers.swift */; }; 14 | AD2713FD22A94AEF004A042C /* ResizableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD2713FC22A94AEF004A042C /* ResizableView.swift */; }; 15 | AD2713FF22A94B11004A042C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD2713FE22A94B11004A042C /* ViewController.swift */; }; 16 | AD27145822AF69C7004A042C /* DraggableResizableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD27145722AF69C7004A042C /* DraggableResizableView.swift */; }; 17 | EFB48DA823E556ED00D1D769 /* AutoLayoutProxy in Frameworks */ = {isa = PBXBuildFile; productRef = EFB48DA723E556ED00D1D769 /* AutoLayoutProxy */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | AD2713E322A94A70004A042C /* AppKit Cocoa Resizable NSView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AppKit Cocoa Resizable NSView.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | AD2713E822A94A72004A042C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | AD2713ED22A94A72004A042C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | AD2713EE22A94A72004A042C /* AppKit_Cocoa_Resizable_NSView.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppKit_Cocoa_Resizable_NSView.entitlements; sourceTree = ""; }; 25 | AD2713F522A94AAF004A042C /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 26 | AD2713F622A94AAF004A042C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 27 | AD2713F722A94AAF004A042C /* NSViewHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSViewHelpers.swift; sourceTree = ""; }; 28 | AD2713FC22A94AEF004A042C /* ResizableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizableView.swift; sourceTree = ""; }; 29 | AD2713FE22A94B11004A042C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 30 | AD27145722AF69C7004A042C /* DraggableResizableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableResizableView.swift; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | AD2713E022A94A70004A042C /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | EFB48DA823E556ED00D1D769 /* AutoLayoutProxy in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | AD2713DA22A94A70004A042C = { 46 | isa = PBXGroup; 47 | children = ( 48 | AD2713E522A94A70004A042C /* AppKit Cocoa Resizable NSView */, 49 | AD2713E422A94A70004A042C /* Products */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | AD2713E422A94A70004A042C /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | AD2713E322A94A70004A042C /* AppKit Cocoa Resizable NSView.app */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | AD2713E522A94A70004A042C /* AppKit Cocoa Resizable NSView */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | AD2713F522A94AAF004A042C /* main.swift */, 65 | AD2713F622A94AAF004A042C /* AppDelegate.swift */, 66 | AD2713FE22A94B11004A042C /* ViewController.swift */, 67 | AD2713FC22A94AEF004A042C /* ResizableView.swift */, 68 | AD27145722AF69C7004A042C /* DraggableResizableView.swift */, 69 | AD2713F722A94AAF004A042C /* NSViewHelpers.swift */, 70 | AD2713E822A94A72004A042C /* Assets.xcassets */, 71 | AD2713ED22A94A72004A042C /* Info.plist */, 72 | AD2713EE22A94A72004A042C /* AppKit_Cocoa_Resizable_NSView.entitlements */, 73 | ); 74 | path = "AppKit Cocoa Resizable NSView"; 75 | sourceTree = ""; 76 | }; 77 | /* End PBXGroup section */ 78 | 79 | /* Begin PBXNativeTarget section */ 80 | AD2713E222A94A70004A042C /* AppKit Cocoa Resizable NSView */ = { 81 | isa = PBXNativeTarget; 82 | buildConfigurationList = AD2713F122A94A72004A042C /* Build configuration list for PBXNativeTarget "AppKit Cocoa Resizable NSView" */; 83 | buildPhases = ( 84 | AD2713DF22A94A70004A042C /* Sources */, 85 | AD2713E022A94A70004A042C /* Frameworks */, 86 | AD2713E122A94A70004A042C /* Resources */, 87 | ); 88 | buildRules = ( 89 | ); 90 | dependencies = ( 91 | ); 92 | name = "AppKit Cocoa Resizable NSView"; 93 | packageProductDependencies = ( 94 | EFB48DA723E556ED00D1D769 /* AutoLayoutProxy */, 95 | ); 96 | productName = "AppKit Cocoa Resizable NSView"; 97 | productReference = AD2713E322A94A70004A042C /* AppKit Cocoa Resizable NSView.app */; 98 | productType = "com.apple.product-type.application"; 99 | }; 100 | /* End PBXNativeTarget section */ 101 | 102 | /* Begin PBXProject section */ 103 | AD2713DB22A94A70004A042C /* Project object */ = { 104 | isa = PBXProject; 105 | attributes = { 106 | LastSwiftUpdateCheck = 1010; 107 | LastUpgradeCheck = 1100; 108 | ORGANIZATIONNAME = "Bibin Jacob Pulickal"; 109 | TargetAttributes = { 110 | AD2713E222A94A70004A042C = { 111 | CreatedOnToolsVersion = 10.1; 112 | LastSwiftMigration = 1100; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = AD2713DE22A94A70004A042C /* Build configuration list for PBXProject "AppKit Cocoa Resizable NSView" */; 117 | compatibilityVersion = "Xcode 9.3"; 118 | developmentRegion = en; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | Base, 123 | ); 124 | mainGroup = AD2713DA22A94A70004A042C; 125 | packageReferences = ( 126 | EFB48DA623E556ED00D1D769 /* XCRemoteSwiftPackageReference "AutoLayoutProxy" */, 127 | ); 128 | productRefGroup = AD2713E422A94A70004A042C /* Products */; 129 | projectDirPath = ""; 130 | projectRoot = ""; 131 | targets = ( 132 | AD2713E222A94A70004A042C /* AppKit Cocoa Resizable NSView */, 133 | ); 134 | }; 135 | /* End PBXProject section */ 136 | 137 | /* Begin PBXResourcesBuildPhase section */ 138 | AD2713E122A94A70004A042C /* Resources */ = { 139 | isa = PBXResourcesBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | AD2713E922A94A72004A042C /* Assets.xcassets in Resources */, 143 | ); 144 | runOnlyForDeploymentPostprocessing = 0; 145 | }; 146 | /* End PBXResourcesBuildPhase section */ 147 | 148 | /* Begin PBXSourcesBuildPhase section */ 149 | AD2713DF22A94A70004A042C /* Sources */ = { 150 | isa = PBXSourcesBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | AD2713FF22A94B11004A042C /* ViewController.swift in Sources */, 154 | AD2713FD22A94AEF004A042C /* ResizableView.swift in Sources */, 155 | AD2713FA22A94AB0004A042C /* AppDelegate.swift in Sources */, 156 | AD2713FB22A94AB0004A042C /* NSViewHelpers.swift in Sources */, 157 | AD27145822AF69C7004A042C /* DraggableResizableView.swift in Sources */, 158 | AD2713F922A94AB0004A042C /* main.swift in Sources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXSourcesBuildPhase section */ 163 | 164 | /* Begin XCBuildConfiguration section */ 165 | AD2713EF22A94A72004A042C /* Debug */ = { 166 | isa = XCBuildConfiguration; 167 | buildSettings = { 168 | ALWAYS_SEARCH_USER_PATHS = NO; 169 | CLANG_ANALYZER_NONNULL = YES; 170 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 171 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 172 | CLANG_CXX_LIBRARY = "libc++"; 173 | CLANG_ENABLE_MODULES = YES; 174 | CLANG_ENABLE_OBJC_ARC = YES; 175 | CLANG_ENABLE_OBJC_WEAK = YES; 176 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 177 | CLANG_WARN_BOOL_CONVERSION = YES; 178 | CLANG_WARN_COMMA = YES; 179 | CLANG_WARN_CONSTANT_CONVERSION = YES; 180 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 183 | CLANG_WARN_EMPTY_BODY = YES; 184 | CLANG_WARN_ENUM_CONVERSION = YES; 185 | CLANG_WARN_INFINITE_RECURSION = YES; 186 | CLANG_WARN_INT_CONVERSION = YES; 187 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 188 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 189 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 190 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 191 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 192 | CLANG_WARN_STRICT_PROTOTYPES = YES; 193 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 194 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 195 | CLANG_WARN_UNREACHABLE_CODE = YES; 196 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 197 | CODE_SIGN_IDENTITY = "-"; 198 | COPY_PHASE_STRIP = NO; 199 | DEBUG_INFORMATION_FORMAT = dwarf; 200 | ENABLE_STRICT_OBJC_MSGSEND = YES; 201 | ENABLE_TESTABILITY = YES; 202 | GCC_C_LANGUAGE_STANDARD = gnu11; 203 | GCC_DYNAMIC_NO_PIC = NO; 204 | GCC_NO_COMMON_BLOCKS = YES; 205 | GCC_OPTIMIZATION_LEVEL = 0; 206 | GCC_PREPROCESSOR_DEFINITIONS = ( 207 | "DEBUG=1", 208 | "$(inherited)", 209 | ); 210 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 211 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 212 | GCC_WARN_UNDECLARED_SELECTOR = YES; 213 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 214 | GCC_WARN_UNUSED_FUNCTION = YES; 215 | GCC_WARN_UNUSED_VARIABLE = YES; 216 | MACOSX_DEPLOYMENT_TARGET = 10.14; 217 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 218 | MTL_FAST_MATH = YES; 219 | ONLY_ACTIVE_ARCH = YES; 220 | SDKROOT = macosx; 221 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 222 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 223 | }; 224 | name = Debug; 225 | }; 226 | AD2713F022A94A72004A042C /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | ALWAYS_SEARCH_USER_PATHS = NO; 230 | CLANG_ANALYZER_NONNULL = YES; 231 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 232 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 233 | CLANG_CXX_LIBRARY = "libc++"; 234 | CLANG_ENABLE_MODULES = YES; 235 | CLANG_ENABLE_OBJC_ARC = YES; 236 | CLANG_ENABLE_OBJC_WEAK = YES; 237 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_COMMA = YES; 240 | CLANG_WARN_CONSTANT_CONVERSION = YES; 241 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 242 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 243 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 244 | CLANG_WARN_EMPTY_BODY = YES; 245 | CLANG_WARN_ENUM_CONVERSION = YES; 246 | CLANG_WARN_INFINITE_RECURSION = YES; 247 | CLANG_WARN_INT_CONVERSION = YES; 248 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 249 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 250 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 251 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 252 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 253 | CLANG_WARN_STRICT_PROTOTYPES = YES; 254 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 255 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 256 | CLANG_WARN_UNREACHABLE_CODE = YES; 257 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 258 | CODE_SIGN_IDENTITY = "-"; 259 | COPY_PHASE_STRIP = NO; 260 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 261 | ENABLE_NS_ASSERTIONS = NO; 262 | ENABLE_STRICT_OBJC_MSGSEND = YES; 263 | GCC_C_LANGUAGE_STANDARD = gnu11; 264 | GCC_NO_COMMON_BLOCKS = YES; 265 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 266 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 267 | GCC_WARN_UNDECLARED_SELECTOR = YES; 268 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 269 | GCC_WARN_UNUSED_FUNCTION = YES; 270 | GCC_WARN_UNUSED_VARIABLE = YES; 271 | MACOSX_DEPLOYMENT_TARGET = 10.14; 272 | MTL_ENABLE_DEBUG_INFO = NO; 273 | MTL_FAST_MATH = YES; 274 | SDKROOT = macosx; 275 | SWIFT_COMPILATION_MODE = wholemodule; 276 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 277 | }; 278 | name = Release; 279 | }; 280 | AD2713F222A94A72004A042C /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 284 | CLANG_ENABLE_MODULES = YES; 285 | CODE_SIGN_ENTITLEMENTS = "AppKit Cocoa Resizable NSView/AppKit_Cocoa_Resizable_NSView.entitlements"; 286 | CODE_SIGN_IDENTITY = "-"; 287 | CODE_SIGN_STYLE = Automatic; 288 | COMBINE_HIDPI_IMAGES = YES; 289 | INFOPLIST_FILE = "AppKit Cocoa Resizable NSView/Info.plist"; 290 | LD_RUNPATH_SEARCH_PATHS = ( 291 | "$(inherited)", 292 | "@executable_path/../Frameworks", 293 | ); 294 | PRODUCT_BUNDLE_IDENTIFIER = "com.pulickan.AppKit-Cocoa-Resizable-NSView"; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 297 | SWIFT_VERSION = 5.0; 298 | }; 299 | name = Debug; 300 | }; 301 | AD2713F322A94A72004A042C /* Release */ = { 302 | isa = XCBuildConfiguration; 303 | buildSettings = { 304 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 305 | CLANG_ENABLE_MODULES = YES; 306 | CODE_SIGN_ENTITLEMENTS = "AppKit Cocoa Resizable NSView/AppKit_Cocoa_Resizable_NSView.entitlements"; 307 | CODE_SIGN_IDENTITY = "-"; 308 | CODE_SIGN_STYLE = Automatic; 309 | COMBINE_HIDPI_IMAGES = YES; 310 | INFOPLIST_FILE = "AppKit Cocoa Resizable NSView/Info.plist"; 311 | LD_RUNPATH_SEARCH_PATHS = ( 312 | "$(inherited)", 313 | "@executable_path/../Frameworks", 314 | ); 315 | PRODUCT_BUNDLE_IDENTIFIER = "com.pulickan.AppKit-Cocoa-Resizable-NSView"; 316 | PRODUCT_NAME = "$(TARGET_NAME)"; 317 | SWIFT_VERSION = 5.0; 318 | }; 319 | name = Release; 320 | }; 321 | /* End XCBuildConfiguration section */ 322 | 323 | /* Begin XCConfigurationList section */ 324 | AD2713DE22A94A70004A042C /* Build configuration list for PBXProject "AppKit Cocoa Resizable NSView" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | AD2713EF22A94A72004A042C /* Debug */, 328 | AD2713F022A94A72004A042C /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | AD2713F122A94A72004A042C /* Build configuration list for PBXNativeTarget "AppKit Cocoa Resizable NSView" */ = { 334 | isa = XCConfigurationList; 335 | buildConfigurations = ( 336 | AD2713F222A94A72004A042C /* Debug */, 337 | AD2713F322A94A72004A042C /* Release */, 338 | ); 339 | defaultConfigurationIsVisible = 0; 340 | defaultConfigurationName = Release; 341 | }; 342 | /* End XCConfigurationList section */ 343 | 344 | /* Begin XCRemoteSwiftPackageReference section */ 345 | EFB48DA623E556ED00D1D769 /* XCRemoteSwiftPackageReference "AutoLayoutProxy" */ = { 346 | isa = XCRemoteSwiftPackageReference; 347 | repositoryURL = "https://github.com/bibinjacobpulickal/AutoLayoutProxy"; 348 | requirement = { 349 | kind = upToNextMajorVersion; 350 | minimumVersion = 2.4.2; 351 | }; 352 | }; 353 | /* End XCRemoteSwiftPackageReference section */ 354 | 355 | /* Begin XCSwiftPackageProductDependency section */ 356 | EFB48DA723E556ED00D1D769 /* AutoLayoutProxy */ = { 357 | isa = XCSwiftPackageProductDependency; 358 | package = EFB48DA623E556ED00D1D769 /* XCRemoteSwiftPackageReference "AutoLayoutProxy" */; 359 | productName = AutoLayoutProxy; 360 | }; 361 | /* End XCSwiftPackageProductDependency section */ 362 | }; 363 | rootObject = AD2713DB22A94A70004A042C /* Project object */; 364 | } 365 | --------------------------------------------------------------------------------