2016-12-16 14 views
0

Я пытаюсь сделать приложение графического калькулятора, и я не могу заставить AxesDrawer работать. Это из университетского курса Стэнфорде с быстрым 2, и я не знаю, как сделать это с помощью UIBezierPath и т.д.AxesDrawer не может рисовать swift3 xcode 8

AxesDrawer.swift:

import UIKit 

class AxesDrawer 
{ 
    private struct Constants { 
     static let HashmarkSize: CGFloat = 6 
    } 

    var color = UIColor.blue 
    var minimumPointsPerHashmark: CGFloat = 40 
    var contentScaleFactor: CGFloat = 1 // set this from UIView's contentScaleFactor to position axes with maximum accuracy 

    convenience init(color: UIColor, contentScaleFactor: CGFloat) { 
     self.init() 
     self.color = color 
     self.contentScaleFactor = contentScaleFactor 
    } 

    convenience init(color: UIColor) { 
     self.init() 
     self.color = color 
    } 

    convenience init(contentScaleFactor: CGFloat) { 
     self.init() 
     self.contentScaleFactor = contentScaleFactor 
    } 

    // this method is the heart of the AxesDrawer 
    // it draws in the current graphic context's coordinate system 
    // therefore origin and bounds must be in the current graphics context's coordinate system 
    // pointsPerUnit is essentially the "scale" of the axes 
    // e.g. if you wanted there to be 100 points along an axis between -1 and 1, 
    // you'd set pointsPerUnit to 50 

    func drawAxesInRect(bounds: CGRect, origin: CGPoint, pointsPerUnit: CGFloat) 
    { 
     UIGraphicsGetCurrentContext()!.saveGState() 
     color.set() 
     let path = UIBezierPath() 
     path.move(to: CGPoint(x: bounds.minX, y: align(coordinate: origin.y))) 
     path.addLine(to: CGPoint(x: bounds.maxX, y: align(coordinate: origin.y))) 
     path.move(to: CGPoint(x: align(coordinate: origin.x), y: bounds.minY)) 
     path.addLine(to: CGPoint(x: align(coordinate: origin.x), y: bounds.maxY)) 
     path.stroke() 
     drawHashmarksInRect(bounds: bounds, origin: origin, pointsPerUnit: abs(pointsPerUnit)) 
     UIGraphicsGetCurrentContext()!.restoreGState() 
    } 

    // the rest of this class is private 

    private func drawHashmarksInRect(bounds: CGRect, origin: CGPoint, pointsPerUnit: CGFloat) 
    { 
     if ((origin.x >= bounds.minX) && (origin.x <= bounds.maxX)) || ((origin.y >= bounds.minY) && (origin.y <= bounds.maxY)) 
     { 
      // figure out how many units each hashmark must represent 
      // to respect both pointsPerUnit and minimumPointsPerHashmark 
      var unitsPerHashmark = minimumPointsPerHashmark/pointsPerUnit 
      if unitsPerHashmark < 1 { 
       unitsPerHashmark = pow(10, ceil(log10(unitsPerHashmark))) 
      } else { 
       unitsPerHashmark = floor(unitsPerHashmark) 
      } 

      let pointsPerHashmark = pointsPerUnit * unitsPerHashmark 

      // figure out which is the closest set of hashmarks (radiating out from the origin) that are in bounds 
      var startingHashmarkRadius: CGFloat = 1 
      if !bounds.contains(origin) { 
       let leftx = max(origin.x - bounds.maxX, 0) 
       let rightx = max(bounds.minX - origin.x, 0) 
       let downy = max(origin.y - bounds.minY, 0) 
       let upy = max(bounds.maxY - origin.y, 0) 
       startingHashmarkRadius = min(min(leftx, rightx), min(downy, upy))/pointsPerHashmark + 1 
      } 

      // now create a bounding box inside whose edges those four hashmarks lie 
      let bboxSize = pointsPerHashmark * startingHashmarkRadius * 2 
      var bbox = CGRect(center: origin, size: CGSize(width: bboxSize, height: bboxSize)) 

      // formatter for the hashmark labels 
      let formatter = NumberFormatter() 
      formatter.maximumFractionDigits = Int(-log10(Double(unitsPerHashmark))) 
      formatter.minimumIntegerDigits = 1 

      // radiate the bbox out until the hashmarks are further out than the bounds 
      while !bbox.contains(bounds) 
      { 

       let label = formatter.string(from: NSNumber(value: Int(origin.x-bbox.minX/pointsPerUnit))) 
       if let leftHashmarkPoint = alignedPoint(x: bbox.minX, y: origin.y, insideBounds:bounds) { 
        drawHashmarkAtLocation(location: leftHashmarkPoint, .Top("-\(label)")) 
       } 
       if let rightHashmarkPoint = alignedPoint(x: bbox.maxX, y: origin.y, insideBounds:bounds) { 
        drawHashmarkAtLocation(location: rightHashmarkPoint, AnchoredText.Top(label!)) 
       } 
       if let topHashmarkPoint = alignedPoint(x: origin.x, y: bbox.minY, insideBounds:bounds) { 
        drawHashmarkAtLocation(location: topHashmarkPoint, AnchoredText.Left(label!)) 
       } 
       if let bottomHashmarkPoint = alignedPoint(x: origin.x, y: bbox.maxY, insideBounds:bounds) { 
        drawHashmarkAtLocation(location: bottomHashmarkPoint, .Left("-\(label)")) 
       } 
       bbox.insetBy(dx: -pointsPerHashmark, dy: -pointsPerHashmark) 
      } 
     } 
    } 

    private func drawHashmarkAtLocation(location: CGPoint, _ text: AnchoredText) 
    { 
     var dx: CGFloat = 0, dy: CGFloat = 0 
     switch text { 
      case .Left: dx = Constants.HashmarkSize/2 
      case .Right: dx = Constants.HashmarkSize/2 
      case .Top: dy = Constants.HashmarkSize/2 
      case .Bottom: dy = Constants.HashmarkSize/2 
     } 

     let path = UIBezierPath() 
     path.move(to: CGPoint(x: location.x-dx, y: location.y-dy)) 
     path.addLine(to: CGPoint(x: location.x+dx, y: location.y+dy)) 
     path.stroke() 

     text.drawAnchoredToPoint(location: location, color: color) 
    } 

    private enum AnchoredText 
    { 
     case Left(String) 
     case Right(String) 
     case Top(String) 
     case Bottom(String) 

     static let VerticalOffset: CGFloat = 3 
     static let HorizontalOffset: CGFloat = 6 

     func drawAnchoredToPoint(location: CGPoint, color: UIColor) { 
      let attributes = [ 
       NSFontAttributeName : UIFont.preferredFont(forTextStyle: UIFontTextStyle.footnote), 
       NSForegroundColorAttributeName : color 
      ] 
      var textRect = CGRect(center: location, size: text.size(attributes: attributes)) 
      switch self { 
       case .Top: textRect.origin.y += textRect.size.height/2 + AnchoredText.VerticalOffset 
       case .Left: textRect.origin.x += textRect.size.width/2 + AnchoredText.HorizontalOffset 
       case .Bottom: textRect.origin.y -= textRect.size.height/2 + AnchoredText.VerticalOffset 
       case .Right: textRect.origin.x -= textRect.size.width/2 + AnchoredText.HorizontalOffset 
      } 
      text.draw(in: textRect, withAttributes: attributes) 
     } 

     var text: String { 
      switch self { 
       case .Left(let text): return text 
       case .Right(let text): return text 
       case .Top(let text): return text 
       case .Bottom(let text): return text 
      } 
     } 
    } 

    // we want the axes and hashmarks to be exactly on pixel boundaries so they look sharp 
    // setting contentScaleFactor properly will enable us to put things on the closest pixel boundary 
    // if contentScaleFactor is left to its default (1), then things will be on the nearest "point" boundary instead 
    // the lines will still be sharp in that case, but might be a pixel (or more theoretically) off of where they should be 

    private func alignedPoint(x x: CGFloat, y: CGFloat, insideBounds: CGRect? = nil) -> CGPoint? 
    { 
     let point = CGPoint(x: align(coordinate: x), y: align(coordinate: y)) 
     if let permissibleBounds = insideBounds, !permissibleBounds.contains(point) { 
      return nil 
     } 
     return point 
    } 

    private func align(coordinate: CGFloat) -> CGFloat { 
     return round(coordinate * contentScaleFactor)/contentScaleFactor 
    } 
} 

extension CGRect 
{ 
    init(center: CGPoint, size: CGSize) { 
     self.init(x: center.x-size.width/2, y: center.y-size.height/2, width: size.width, height: size.height) 
    } 
} 

ViewController.swift: 

    import UIKit 
var calculatorCount = 0 
class CalculatorViewController: UIViewController { 
    var graphl = GraphView() 
    private var on = true 
    @IBOutlet private var display: UILabel! 

    private var userIsInTheMiddleOfTyping = false 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     calculatorCount += 1 
     //print("Loaded up a new Calculator (count = \(calculatorCount))") 
     brain.addUnaryOperation(symbol: "Z") { [ weak weakSelf = self ] in 
      weakSelf?.display.textColor = UIColor.red 
      return sqrt($0) 
     } 
     graphl.print2() 
    } 


    deinit { 
     calculatorCount -= 1 
     //print(" Calculator left the heap (count = \(calculatorCount))") 
    } 


    @IBAction func off(_ sender: UIButton) { 
     on = false 
    } 

    @IBAction func on(_ sender: UIButton) { 
     on = true 
    } 

    @IBAction private func tocuhDigit(_ sender: UIButton) { 
     if on { 
      let digit = sender.currentTitle! 
      if userIsInTheMiddleOfTyping { 
       let textCurrentlyInDisplay = display.text! 
       display.text = textCurrentlyInDisplay + digit 
      } else { 
       display.text = digit 
      } 
      userIsInTheMiddleOfTyping = true 
     } 
    } 
    private var displayValue: Double { 
     get { 
      return Double(display.text!)! 
     } 
     set { 
      display.text = String(newValue) 

     } 
    } 
    var savedProgram: CalculatorBrain.PropertyList? 
    @IBAction func save() { 
     savedProgram = brain.program 

    } 

    @IBAction func restore() { 
     if savedProgram != nil { 
      brain.program = savedProgram! 
      displayValue = brain.result 
     } 
    } 

    private var brain = CalculatorBrain() 

    @IBAction func Reset(_ sender: UIButton) { 
     if on { 

      displayValue = 0 
     } 
    } 
    @IBAction private func performOperation(_ sender: UIButton) { 
     if userIsInTheMiddleOfTyping && on { 
      brain.setOperand(operand: displayValue) 
      userIsInTheMiddleOfTyping = false 
     } 

     if let mathematicalSymbol = sender.currentTitle { 
      brain.perofrmOperation(symbol: mathematicalSymbol) 

     } 
     displayValue = brain.result 
    } 

} 

CalculatorBrain.swift: 

    import Foundation 


class CalculatorBrain { 

    private var accumulator = 0.0 
    private var internalProgram = [AnyObject]() 

    func setOperand(operand: Double) { 
     accumulator = operand 
     internalProgram.append(operand as AnyObject) 

    } 
    func addUnaryOperation(symbol: String, operation: @escaping (Double) -> Double) { 
     operations[symbol] = Operation.UnaryOperation(operation) 
    } 

    private var operations: Dictionary<String, Operation> = [ 
     "π" :Operation.Constant(M_PI), 
     "e" : Operation.Constant(M_E), 
     "±" : Operation.UnaryOperation({ -$0 }), 
     "∓" : Operation.UnaryOperation({+$0}), 
     "√" : Operation.UnaryOperation(sqrt), //sqrt, 
     "cos" : Operation.UnaryOperation(cos), 
     "×" : Operation.BinaryOperation({ $0 * $1 }), 
     "-" : Operation.BinaryOperation({ $0 - $1 }), 
     "+" : Operation.BinaryOperation({ $0 + $1 }), 
     "÷" : Operation.BinaryOperation({ $0/$1 }), 
     "=" : Operation.Equals, 
     "i" : Operation.Constant(sqrt(-1)), 
     "x2" : Operation.UnaryOperation({$0 * $0}), 
     "xb" : Operation.BinaryOperation2({pow($0, $1)}) 
    ] 

    private enum Operation { 
     case Constant(Double) 
     case UnaryOperation((Double) -> Double) 
     case BinaryOperation((Double, Double) -> Double) 
     case Equals 
     case BinaryOperation2((Double, Double) -> Double) 

    } 

    func perofrmOperation(symbol: String) { 
     internalProgram.append(symbol as AnyObject) 
     if let operation = operations[symbol] { 
      switch operation { 
      case .Constant(let value): accumulator = value 
      case .UnaryOperation(let function): accumulator = function(accumulator) 
      case .BinaryOperation(let function): executePendingBinaryOperation() 
      pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator) 
      case .Equals: 
       executePendingBinaryOperation() 

      case .BinaryOperation2(let function): 
       pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator) 




      } 
     } 


    } 
    private func executePendingBinaryOperation() { 
     if pending != nil { 
      accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator) 
     } 
    } 

    private var pending: PendingBinaryOperationInfo? 

    private struct PendingBinaryOperationInfo { 
     var binaryFunction: (Double, Double) -> Double 
     var firstOperand: Double 

    } 

    typealias PropertyList = AnyObject 
    var program: PropertyList { 
     get { 
      return internalProgram as CalculatorBrain.PropertyList 
     } 
     set { 
      clear() 
      if let arrayOfOps = newValue as? [AnyObject] { 
       for op in arrayOfOps { 
        if let operand = op as? Double { 
         setOperand(operand: operand) 
        } else if let operation = op as? String { 
         perofrmOperation(symbol: operation) 
        } 
       } 
      } 
     } 
    } 
    func clear() { 
     accumulator = 0.0 
     pending = nil 
     internalProgram.removeAll() 
    } 

    var result: Double { 
     get { 
      return accumulator 

     } 
    } 

} 

AppDelegate.swift: 

    import UIKit 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
     // Override point for customization after application launch. 
     return true 
    } 

    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 invalidate graphics rendering callbacks. Games should use this method to pause the game. 
    } 

    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) { 
     // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 
    } 

    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) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    } 


} 

Main.storyboard: 
[buttons are in stack a stack view and created a UIView for the graph][1] 


    [1]: https://i.stack.imgur.com/oxwmw.png 

ответ

0

Я знаю, что есть много времени, так как вопрос было сделано, но я сделал один и тот же вопрос сегодня, и я надеюсь, что этот ответ может помочь другим:

Вы можете выполнить следующие действия:

  1. Создать новый проект Xcode.
  2. Добавить файл «AxesDrawer.swift» в свой проект (File -> Добавить файлы в «Projectname» ...
  3. Создать новый Cocoa Touch класса файл с помощью подкласса UIView на главной папке вашего проекта .
  4. Добавить Вид на Main.storyboard и установить имя класса этой точки зрения, равный файл, созданный выше.
  5. Используйте следующий код, чтобы переопределить функцию отрисовки в файле CREA Ted на шаге 3:

    переопределение Func ничьи (_ Прямоугольник: CGRect) {

    //Draw axes 
    let axes: AxesDrawer = AxesDrawer.init(color: UIColor.black, contentScaleFactor: CGFloat(1)) 
    
    axes.drawAxes(in: CGRect(origin: CGPoint(x: bounds.midX, y: bounds.midY), 
             size: CGSize(width: 1000, height: -1000)), 
           origin: CGPoint(x: bounds.midX, y: bounds.midY), 
           pointsPerUnit: CGFloat(2)) 
    
    axes.drawAxes(in: CGRect(origin: CGPoint(x: bounds.midX, y: bounds.midY), 
             size: CGSize(width: -1000, height: 1000)), 
           origin: CGPoint(x: bounds.midX, y: bounds.midY), 
           pointsPerUnit: CGFloat(2)) 
    //End Draw axes 
    

    }

-2
// 
// AxesDrawer.swift 
// Calculator 
// 
// Created by CS193p Instructor. 
// Copyright © 2015-17 Stanford University. 
// All rights reserved. 
// 

import UIKit 

struct AxesDrawer 
{ 
    var color: UIColor 
    var contentScaleFactor: CGFloat    // set this from UIView's contentScaleFactor to position axes with maximum accuracy 
    var minimumPointsPerHashmark: CGFloat = 40 // public even though init doesn't accommodate setting it (it's rare to want to change it) 

    init(color: UIColor = UIColor.blue, contentScaleFactor: CGFloat = 1) { 
     self.color = color 
     self.contentScaleFactor = contentScaleFactor 
    } 

    // this method is the heart of the AxesDrawer 
    // it draws in the current graphic context's coordinate system 
    // therefore origin and bounds must be in the current graphics context's coordinate system 
    // pointsPerUnit is essentially the "scale" of the axes 
    // e.g. if you wanted there to be 100 points along an axis between -1 and 1, 
    // you'd set pointsPerUnit to 50 

    func drawAxes(in rect: CGRect, origin: CGPoint, pointsPerUnit: CGFloat) 
    { 
     UIGraphicsGetCurrentContext()?.saveGState() 
     color.set() 
     let path = UIBezierPath() 
     path.move(to: CGPoint(x: rect.minX, y: origin.y).aligned(usingScaleFactor: contentScaleFactor)!) 
     path.addLine(to: CGPoint(x: rect.maxX, y: origin.y).aligned(usingScaleFactor: contentScaleFactor)!) 
     path.move(to: CGPoint(x: origin.x, y: rect.minY).aligned(usingScaleFactor: contentScaleFactor)!) 
     path.addLine(to: CGPoint(x: origin.x, y: rect.maxY).aligned(usingScaleFactor: contentScaleFactor)!) 
     path.stroke() 
     drawHashmarks(in: rect, origin: origin, pointsPerUnit: abs(pointsPerUnit)) 
     UIGraphicsGetCurrentContext()?.restoreGState() 
    } 

    // the rest of this class is private 

    private struct Constants { 
     static let hashmarkSize: CGFloat = 6 
    } 

    private let formatter = NumberFormatter() // formatter for the hashmark labels 

    private func drawHashmarks(in rect: CGRect, origin: CGPoint, pointsPerUnit: CGFloat) 
    { 
     if ((origin.x >= rect.minX) && (origin.x <= rect.maxX)) || ((origin.y >= rect.minY) && (origin.y <= rect.maxY)) 
     { 
      // figure out how many units each hashmark must represent 
      // to respect both pointsPerUnit and minimumPointsPerHashmark 
      var unitsPerHashmark = minimumPointsPerHashmark/pointsPerUnit 
      if unitsPerHashmark < 1 { 
       unitsPerHashmark = pow(10, ceil(log10(unitsPerHashmark))) 
      } else { 
       unitsPerHashmark = floor(unitsPerHashmark) 
      } 

      let pointsPerHashmark = pointsPerUnit * unitsPerHashmark 

      // figure out which is the closest set of hashmarks (radiating out from the origin) that are in rect 
      var startingHashmarkRadius: CGFloat = 1 
      if !rect.contains(origin) { 
       let leftx = max(origin.x - rect.maxX, 0) 
       let rightx = max(rect.minX - origin.x, 0) 
       let downy = max(origin.y - rect.minY, 0) 
       let upy = max(rect.maxY - origin.y, 0) 
       startingHashmarkRadius = min(min(leftx, rightx), min(downy, upy))/pointsPerHashmark + 1 
      } 

      // pick a reasonable number of fraction digits 
      formatter.maximumFractionDigits = Int(-log10(Double(unitsPerHashmark))) 
      formatter.minimumIntegerDigits = 1 

      // now create a bounding box inside whose edges those four hashmarks lie 
      let bboxSize = pointsPerHashmark * startingHashmarkRadius * 2 
      var bbox = CGRect(center: origin, size: CGSize(width: bboxSize, height: bboxSize)) 

      // radiate the bbox out until the hashmarks are further out than the rect 
      while !bbox.contains(rect) 
      { 
       let label = formatter.string(from: (origin.x-bbox.minX)/pointsPerUnit)! 
       if let leftHashmarkPoint = CGPoint(x: bbox.minX, y: origin.y).aligned(inside: rect, usingScaleFactor: contentScaleFactor) { 
        drawHashmark(at: leftHashmarkPoint, label: .top("-\(label)")) 
       } 
       if let rightHashmarkPoint = CGPoint(x: bbox.maxX, y: origin.y).aligned(inside: rect, usingScaleFactor: contentScaleFactor) { 
        drawHashmark(at: rightHashmarkPoint, label: .top(label)) 
       } 
       if let topHashmarkPoint = CGPoint(x: origin.x, y: bbox.minY).aligned(inside: rect, usingScaleFactor: contentScaleFactor) { 
        drawHashmark(at: topHashmarkPoint, label: .left(label)) 
       } 
       if let bottomHashmarkPoint = CGPoint(x: origin.x, y: bbox.maxY).aligned(inside: rect, usingScaleFactor: contentScaleFactor) { 
        drawHashmark(at: bottomHashmarkPoint, label: .left("-\(label)")) 
       } 
       bbox = bbox.insetBy(dx: -pointsPerHashmark, dy: -pointsPerHashmark) 
      } 
     } 
    } 

    private func drawHashmark(at location: CGPoint, label: AnchoredText) 
    { 
     var dx: CGFloat = 0, dy: CGFloat = 0 
     switch label { 
      case .left: dx = Constants.hashmarkSize/2 
      case .right: dx = Constants.hashmarkSize/2 
      case .top: dy = Constants.hashmarkSize/2 
      case .bottom: dy = Constants.hashmarkSize/2 
     } 

     let path = UIBezierPath() 
     path.move(to: CGPoint(x: location.x-dx, y: location.y-dy)) 
     path.addLine(to: CGPoint(x: location.x+dx, y: location.y+dy)) 
     path.stroke() 

     label.draw(at: location, usingColor: color) 
    } 

    private enum AnchoredText 
    { 
     case left(String) 
     case right(String) 
     case top(String) 
     case bottom(String) 

     static let verticalOffset: CGFloat = 3 
     static let horizontalOffset: CGFloat = 6 

     func draw(at location: CGPoint, usingColor color: UIColor) { 
      let attributes = [ 
       NSFontAttributeName : UIFont.preferredFont(forTextStyle: .footnote), 
       NSForegroundColorAttributeName : color 
      ] 
      var textRect = CGRect(center: location, size: text.size(attributes: attributes)) 
      switch self { 
       case .top: textRect.origin.y += textRect.size.height/2 + AnchoredText.verticalOffset 
       case .left: textRect.origin.x += textRect.size.width/2 + AnchoredText.horizontalOffset 
       case .bottom: textRect.origin.y -= textRect.size.height/2 + AnchoredText.verticalOffset 
       case .right: textRect.origin.x -= textRect.size.width/2 + AnchoredText.horizontalOffset 
      } 
      text.draw(in: textRect, withAttributes: attributes) 
     } 

     var text: String { 
      switch self { 
       case .left(let text): return text 
       case .right(let text): return text 
       case .top(let text): return text 
       case .bottom(let text): return text 
      } 
     } 
    } 
} 

private extension CGPoint 
{ 
    func aligned(inside bounds: CGRect? = nil, usingScaleFactor scaleFactor: CGFloat = 1.0) -> CGPoint? 
    { 
     func align(_ coordinate: CGFloat) -> CGFloat { 
      return round(coordinate * scaleFactor)/scaleFactor 
     } 
     let point = CGPoint(x: align(x), y: align(y)) 
     if let permissibleBounds = bounds, !permissibleBounds.contains(point) { 
      return nil 
     } 
     return point 
    } 
} 

private extension NumberFormatter 
{ 
    func string(from point: CGFloat) -> String? { 
     return string(from: NSNumber(value: Double(point))) 
    } 
} 

private extension CGRect 
{ 
    init(center: CGPoint, size: CGSize) { 
     self.init(x: center.x-size.width/2, y: center.y-size.height/2, width: size.width, height: size.height) 
    } 
} 
+0

При ответе на вопрос, объяснить, что у вас есть вместо того, чтобы отправлять весь код вместе. См. [Как ответить] (https://stackoverflow.com/help/how-to-answer) – siddiq

 Смежные вопросы

  • Нет связанных вопросов^_^