diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bf5374 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Resizable.xcodeproj/xcuserdata +Resizable.xcodeproj/project.xcworkspace/xcuserdata diff --git a/README.md b/README.md index b7730c6..84e0ee9 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,7 @@ Dragging on the corner handles will resize the view from from the opposite corne Dragging on the rotate handle will adjust the CGAffineTransform rotation value of the view. Dragging on the middle of the view will adjust the view's center position. + + + + diff --git a/Resizable.xcodeproj/project.pbxproj b/Resizable.xcodeproj/project.pbxproj index 11d7b71..db16792 100644 --- a/Resizable.xcodeproj/project.pbxproj +++ b/Resizable.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ 82982CC919BAE60C00D257C1 /* ResizableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82982CC819BAE60C00D257C1 /* ResizableView.swift */; }; 82982CCB19BB263100D257C1 /* UIView+Transform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82982CCA19BB263100D257C1 /* UIView+Transform.swift */; }; 82982CCD19BBDAE400D257C1 /* DragHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82982CCC19BBDAE400D257C1 /* DragHandle.swift */; }; + CBE5B5561E60B22300E7A142 /* ResizeBorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBE5B5551E60B22300E7A142 /* ResizeBorder.swift */; }; + CBE5B55A1E60B41200E7A142 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = CBE5B5591E60B41200E7A142 /* LaunchScreen.xib */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,6 +42,8 @@ 82982CC819BAE60C00D257C1 /* ResizableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResizableView.swift; sourceTree = ""; }; 82982CCA19BB263100D257C1 /* UIView+Transform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Transform.swift"; sourceTree = ""; }; 82982CCC19BBDAE400D257C1 /* DragHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DragHandle.swift; sourceTree = ""; }; + CBE5B5551E60B22300E7A142 /* ResizeBorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResizeBorder.swift; sourceTree = ""; }; + CBE5B5591E60B41200E7A142 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -81,12 +85,14 @@ 82982CA819BAE5EA00D257C1 /* Resizable */ = { isa = PBXGroup; children = ( + CBE5B5551E60B22300E7A142 /* ResizeBorder.swift */, 82982CAB19BAE5EA00D257C1 /* AppDelegate.swift */, 82982CAD19BAE5EA00D257C1 /* ViewController.swift */, 82982CC819BAE60C00D257C1 /* ResizableView.swift */, 82982CCC19BBDAE400D257C1 /* DragHandle.swift */, 82982CCA19BB263100D257C1 /* UIView+Transform.swift */, 82982CAF19BAE5EA00D257C1 /* Main.storyboard */, + CBE5B5591E60B41200E7A142 /* LaunchScreen.xib */, 82982CB219BAE5EA00D257C1 /* Images.xcassets */, 82982CA919BAE5EA00D257C1 /* Supporting Files */, ); @@ -162,14 +168,16 @@ 82982C9E19BAE5EA00D257C1 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = Caroline; TargetAttributes = { 82982CA519BAE5EA00D257C1 = { CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0820; }; 82982CB719BAE5EA00D257C1 = { CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0820; TestTargetID = 82982CA519BAE5EA00D257C1; }; }; @@ -198,6 +206,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + CBE5B55A1E60B41200E7A142 /* LaunchScreen.xib in Resources */, 82982CB119BAE5EA00D257C1 /* Main.storyboard in Resources */, 82982CB319BAE5EA00D257C1 /* Images.xcassets in Resources */, ); @@ -222,6 +231,7 @@ 82982CAC19BAE5EA00D257C1 /* AppDelegate.swift in Sources */, 82982CC919BAE60C00D257C1 /* ResizableView.swift in Sources */, 82982CCB19BB263100D257C1 /* UIView+Transform.swift in Sources */, + CBE5B5561E60B22300E7A142 /* ResizeBorder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -268,15 +278,19 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -310,8 +324,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -319,6 +335,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -328,6 +345,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -336,10 +354,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; INFOPLIST_FILE = Resizable/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.caroline.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -347,10 +366,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; INFOPLIST_FILE = Resizable/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.caroline.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -368,7 +388,9 @@ ); INFOPLIST_FILE = ResizableTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.caroline.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Resizable.app/Resizable"; }; name = Debug; @@ -383,7 +405,9 @@ ); INFOPLIST_FILE = ResizableTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.caroline.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Resizable.app/Resizable"; }; name = Release; @@ -407,6 +431,7 @@ 82982CC419BAE5EA00D257C1 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 82982CC519BAE5EA00D257C1 /* Build configuration list for PBXNativeTarget "ResizableTests" */ = { isa = XCConfigurationList; @@ -415,6 +440,7 @@ 82982CC719BAE5EA00D257C1 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Resizable/AppDelegate.swift b/Resizable/AppDelegate.swift index d48d70f..f436318 100644 --- a/Resizable/AppDelegate.swift +++ b/Resizable/AppDelegate.swift @@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/Resizable/DragHandle.swift b/Resizable/DragHandle.swift index 72a29ff..86b4660 100644 --- a/Resizable/DragHandle.swift +++ b/Resizable/DragHandle.swift @@ -12,8 +12,8 @@ import UIKit class DragHandle: UIView { - var fillColor = UIColor.darkGrayColor() - var strokeColor = UIColor.lightGrayColor() + var fillColor = UIColor.darkGray + var strokeColor = UIColor.lightGray var strokeWidth:CGFloat = 2.0 required init(coder aDecoder: NSCoder) { @@ -21,17 +21,17 @@ class DragHandle: UIView { } init(fillColor:UIColor, strokeColor:UIColor, strokeWidth width:CGFloat = 2.0) { - super.init(frame:CGRectMake(0, 0, diameter, diameter)) + super.init(frame:CGRect(x: 0, y: 0, width: diameter, height: diameter)) self.fillColor = fillColor self.strokeColor = strokeColor self.strokeWidth = width - self.backgroundColor = UIColor.clearColor() + self.backgroundColor = UIColor.clear } - override func drawRect(rect: CGRect) + override func draw(_ rect: CGRect) { - super.drawRect(rect) - var handlePath = UIBezierPath(ovalInRect: CGRectInset(rect, 10 + strokeWidth, 10 + strokeWidth)) + super.draw(rect) + let handlePath = UIBezierPath(ovalIn: rect.insetBy(dx: 10 + strokeWidth, dy: 10 + strokeWidth)) fillColor.setFill() handlePath.fill() strokeColor.setStroke() diff --git a/Resizable/Images.xcassets/AppIcon.appiconset/Contents.json b/Resizable/Images.xcassets/AppIcon.appiconset/Contents.json index a396706..b8236c6 100644 --- a/Resizable/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Resizable/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,19 +1,44 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" } ], "info" : { diff --git a/Resizable/Info.plist b/Resizable/Info.plist index 9bc3ce0..6905cc6 100644 --- a/Resizable/Info.plist +++ b/Resizable/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.caroline.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,6 +22,8 @@ 1 LSRequiresIPhoneOS + UILaunchStoryboardName + LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities diff --git a/Resizable/LaunchScreen.xib b/Resizable/LaunchScreen.xib new file mode 100644 index 0000000..133d94a --- /dev/null +++ b/Resizable/LaunchScreen.xib @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resizable/ResizableView.swift b/Resizable/ResizableView.swift index 78c6eae..1f9d2c4 100644 --- a/Resizable/ResizableView.swift +++ b/Resizable/ResizableView.swift @@ -15,15 +15,16 @@ class ResizableView: UIView { var bottomLeft:DragHandle! var bottomRight:DragHandle! var rotateHandle:DragHandle! - var previousLocation = CGPointZero + var borderView:ResizeBorder! + var previousLocation = CGPoint.zero var rotateLine = CAShapeLayer() override func didMoveToSuperview() { - let resizeFillColor = UIColor.cyanColor() - let resizeStrokeColor = UIColor.blackColor() - let rotateFillColor = UIColor.orangeColor() - let rotateStrokeColor = UIColor.blackColor() + let resizeFillColor = UIColor.cyan + let resizeStrokeColor = UIColor.black + let rotateFillColor = UIColor.orange + let rotateStrokeColor = UIColor.black topLeft = DragHandle(fillColor:resizeFillColor, strokeColor: resizeStrokeColor) topRight = DragHandle(fillColor:resizeFillColor, strokeColor: resizeStrokeColor) bottomLeft = DragHandle(fillColor:resizeFillColor, strokeColor: resizeStrokeColor) @@ -33,6 +34,10 @@ class ResizableView: UIView { rotateLine.opacity = 0.0 rotateLine.lineDashPattern = [3,2] + borderView = ResizeBorder(frame:self.bounds) + borderView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + self.addSubview(borderView) + superview?.addSubview(topLeft) superview?.addSubview(topRight) superview?.addSubview(bottomLeft) @@ -41,17 +46,17 @@ class ResizableView: UIView { self.layer.addSublayer(rotateLine) - var pan = UIPanGestureRecognizer(target: self, action: "handlePan:") + var pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handlePan(_:))) topLeft.addGestureRecognizer(pan) - pan = UIPanGestureRecognizer(target: self, action: "handlePan:") + pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handlePan(_:))) topRight.addGestureRecognizer(pan) - pan = UIPanGestureRecognizer(target: self, action: "handlePan:") + pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handlePan(_:))) bottomLeft.addGestureRecognizer(pan) - pan = UIPanGestureRecognizer(target: self, action: "handlePan:") + pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handlePan(_:))) bottomRight.addGestureRecognizer(pan) - pan = UIPanGestureRecognizer(target: self, action: "handleRotate:") + pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handleRotate(_:))) rotateHandle.addGestureRecognizer(pan) - pan = UIPanGestureRecognizer(target: self, action: "handleMove:") + pan = UIPanGestureRecognizer(target: self, action: #selector(ResizableView.handleMove(_:))) self.addGestureRecognizer(pan) self.updateDragHandles() @@ -63,23 +68,26 @@ class ResizableView: UIView { bottomLeft.center = self.transformedBottomLeft() bottomRight.center = self.transformedBottomRight() rotateHandle.center = self.transformedRotateHandle() + + borderView.bounds = self.bounds + borderView.setNeedsDisplay() } //MARK: - Gesture Methods - func handleMove(gesture:UIPanGestureRecognizer) { - let translation = gesture.translationInView(self.superview!) + func handleMove(_ gesture:UIPanGestureRecognizer) { + let translation = gesture.translation(in: self.superview!) var center = self.center center.x += translation.x center.y += translation.y self.center = center - gesture.setTranslation(CGPointZero, inView: self.superview!) + gesture.setTranslation(CGPoint.zero, in: self.superview!) updateDragHandles() } - func angleBetweenPoints(startPoint:CGPoint, endPoint:CGPoint) -> CGFloat { + func angleBetweenPoints(_ startPoint:CGPoint, endPoint:CGPoint) -> CGFloat { let a = startPoint.x - self.center.x let b = startPoint.y - self.center.y let c = endPoint.x - self.center.x @@ -90,68 +98,68 @@ class ResizableView: UIView { } - func drawRotateLine(fromPoint:CGPoint, toPoint:CGPoint) { - var linePath = UIBezierPath() - linePath.moveToPoint(fromPoint) - linePath.addLineToPoint(toPoint) - rotateLine.path = linePath.CGPath + func drawRotateLine(_ fromPoint:CGPoint, toPoint:CGPoint) { + let linePath = UIBezierPath() + linePath.move(to: fromPoint) + linePath.addLine(to: toPoint) + rotateLine.path = linePath.cgPath rotateLine.fillColor = nil - rotateLine.strokeColor = UIColor.orangeColor().CGColor + rotateLine.strokeColor = UIColor.orange.cgColor rotateLine.lineWidth = 2.0 rotateLine.opacity = 1.0 } - func handleRotate(gesture:UIPanGestureRecognizer) { + func handleRotate(_ gesture:UIPanGestureRecognizer) { switch gesture.state { - case .Began: + case .began: previousLocation = rotateHandle.center - self.drawRotateLine(CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2), toPoint:CGPointMake(self.bounds.size.width + diameter, self.bounds.size.height/2)) - case .Ended: + self.drawRotateLine(CGPoint(x: self.bounds.size.width/2, y: self.bounds.size.height/2), toPoint:CGPoint(x: self.bounds.size.width + diameter, y: self.bounds.size.height/2)) + case .ended: self.rotateLine.opacity = 0.0 default:() } - let location = gesture.locationInView(self.superview!) + let location = gesture.location(in: self.superview!) let angle = angleBetweenPoints(previousLocation, endPoint: location) - self.transform = CGAffineTransformRotate(self.transform, angle) + self.transform = self.transform.rotated(by: angle) previousLocation = location self.updateDragHandles() } - func handlePan(gesture:UIPanGestureRecognizer) { - var translation = gesture.translationInView(self) + func handlePan(_ gesture:UIPanGestureRecognizer) { + let translation = gesture.translation(in: self) switch gesture.view! { case topLeft: - if gesture.state == .Began { - self.setAnchorPoint(CGPointMake(1, 1)) + if gesture.state == .began { + self.setAnchorPoint(CGPoint(x: 1, y: 1)) } self.bounds.size.width -= translation.x self.bounds.size.height -= translation.y case topRight: - if gesture.state == .Began { - self.setAnchorPoint(CGPointMake(0, 1)) + if gesture.state == .began { + self.setAnchorPoint(CGPoint(x: 0, y: 1)) } self.bounds.size.width += translation.x self.bounds.size.height -= translation.y case bottomLeft: - if gesture.state == .Began { - self.setAnchorPoint(CGPointMake(1, 0)) + if gesture.state == .began { + self.setAnchorPoint(CGPoint(x: 1, y: 0)) } self.bounds.size.width -= translation.x self.bounds.size.height += translation.y case bottomRight: - if gesture.state == .Began { - self.setAnchorPoint(CGPointZero) + if gesture.state == .began { + self.setAnchorPoint(CGPoint.zero) } self.bounds.size.width += translation.x self.bounds.size.height += translation.y default:() } - gesture.setTranslation(CGPointZero, inView: self) + gesture.setTranslation(CGPoint.zero, in: self) updateDragHandles() - if gesture.state == .Ended { - self.setAnchorPoint(CGPointMake(0.5, 0.5)) + if gesture.state == .ended { + self.setAnchorPoint(CGPoint(x: 0.5, y: 0.5)) } } } diff --git a/Resizable/ResizeBorder.swift b/Resizable/ResizeBorder.swift new file mode 100755 index 0000000..b214ffb --- /dev/null +++ b/Resizable/ResizeBorder.swift @@ -0,0 +1,49 @@ +// +// ResizeBorder.swift +// Resizable +// +// Created by Adil Soomro on 7/02/2017. +// Copyright (c) 2017 BooleanBites Ltd. All rights reserved. +// + + + +import UIKit + +let dash1: CGFloat = 2.0 +let dash2: CGFloat = 4.0 + +let lineWidth: CGFloat = 2.5 + +let dash:[CGFloat] = [dash1, dash2] + +class ResizeBorder: UIView { + override init(frame: CGRect) { + super.init(frame: frame) + self.backgroundColor = UIColor.clear + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.backgroundColor = UIColor.clear + } + + override func draw(_ rect: CGRect) + { + + + let context = UIGraphicsGetCurrentContext(); + context!.saveGState(); + + context!.setLineWidth(lineWidth); + + + context?.setLineDash(phase: 0.0, lengths: dash) + + context!.setStrokeColor(UIColor.black.cgColor); + context!.addRect(self.bounds); + context!.strokePath(); + + context!.restoreGState(); + } +} diff --git a/Resizable/UIView+Transform.swift b/Resizable/UIView+Transform.swift index c1dfe22..8ab1e09 100644 --- a/Resizable/UIView+Transform.swift +++ b/Resizable/UIView+Transform.swift @@ -15,24 +15,24 @@ import UIKit extension UIView { - func offsetPointToParentCoordinates(point: CGPoint) -> CGPoint { - return CGPointMake(point.x + self.center.x, point.y + self.center.y) + func offsetPointToParentCoordinates(_ point: CGPoint) -> CGPoint { + return CGPoint(x: point.x + self.center.x, y: point.y + self.center.y) } - func pointInViewCenterTerms(point:CGPoint) -> CGPoint { - return CGPointMake(point.x - self.center.x, point.y - self.center.y) + func pointInViewCenterTerms(_ point:CGPoint) -> CGPoint { + return CGPoint(x: point.x - self.center.x, y: point.y - self.center.y) } - func pointInTransformedView(point: CGPoint) -> CGPoint { + func pointInTransformedView(_ point: CGPoint) -> CGPoint { let offsetItem = self.pointInViewCenterTerms(point) - let updatedItem = CGPointApplyAffineTransform(offsetItem, self.transform) + let updatedItem = offsetItem.applying(self.transform) let finalItem = self.offsetPointToParentCoordinates(updatedItem) return finalItem } func originalFrame() -> CGRect { let currentTransform = self.transform - self.transform = CGAffineTransformIdentity + self.transform = CGAffineTransform.identity let originalFrame = self.frame self.transform = currentTransform return originalFrame @@ -77,12 +77,12 @@ extension UIView { return self.pointInTransformedView(point) } - func setAnchorPoint(anchorPoint:CGPoint) { - var newPoint = CGPointMake(self.bounds.size.width * anchorPoint.x, self.bounds.size.height * anchorPoint.y) - var oldPoint = CGPointMake(self.bounds.size.width * self.layer.anchorPoint.x, self.bounds.size.height * self.layer.anchorPoint.y) + func setAnchorPoint(_ anchorPoint:CGPoint) { + var newPoint = CGPoint(x: self.bounds.size.width * anchorPoint.x, y: self.bounds.size.height * anchorPoint.y) + var oldPoint = CGPoint(x: self.bounds.size.width * self.layer.anchorPoint.x, y: self.bounds.size.height * self.layer.anchorPoint.y) - newPoint = CGPointApplyAffineTransform(newPoint, self.transform) - oldPoint = CGPointApplyAffineTransform(oldPoint, self.transform) + newPoint = newPoint.applying(self.transform) + oldPoint = oldPoint.applying(self.transform) var position = self.layer.position position.x -= oldPoint.x @@ -94,4 +94,4 @@ extension UIView { self.layer.anchorPoint = anchorPoint } -} \ No newline at end of file +} diff --git a/Resizable/ViewController.swift b/Resizable/ViewController.swift index 0d56118..173b321 100644 --- a/Resizable/ViewController.swift +++ b/Resizable/ViewController.swift @@ -12,10 +12,9 @@ import QuartzCore class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - var resizableView = ResizableView(frame: CGRectMake(60, 100, 200, 200)) - resizableView.backgroundColor = UIColor.purpleColor() - resizableView.transform = CGAffineTransformMakeRotation(0.3) - resizableView.center = CGPointMake(160, 200) + let resizableView = ResizableView(frame: CGRect(x: 60, y: 100, width: 200, height: 200)) + resizableView.backgroundColor = UIColor.lightGray + resizableView.center = CGPoint(x: 160, y: 200) self.view.addSubview(resizableView) } } diff --git a/ResizableTests/Info.plist b/ResizableTests/Info.plist index 6e1bebb..ba72822 100644 --- a/ResizableTests/Info.plist +++ b/ResizableTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.caroline.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/ResizableTests/ResizableTests.swift b/ResizableTests/ResizableTests.swift index dd9b561..e0eb218 100644 --- a/ResizableTests/ResizableTests.swift +++ b/ResizableTests/ResizableTests.swift @@ -28,7 +28,7 @@ class ResizableTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock() { + self.measure() { // Put the code you want to measure the time of here. } } diff --git a/Sample.png b/Sample.png new file mode 100644 index 0000000..cb1c2af Binary files /dev/null and b/Sample.png differ