CGRectMake, CGPointMake, CGSizeMake, CGRectZero, CGPointZero is unavailable in Swift - uikit

After converting code to latest swift 3.0 I am shown this error.
Also tell me solution for CGSize = CGSizeMake(0,0)
static var frameAtStartOfPan: CGRect = CGRectZero
static var startPointOfPan: CGPoint = CGPointZero
Which is also unavailable.

CGRect Can be simply created using an instance of a CGPoint or CGSize, thats given below.
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 100, height: 100))
// Or
let rect = CGRect(origin: .zero, size: CGSize(width: 100, height: 100))
Or if we want to specify each value in CGFloat or Double or Int, we can use this method.
let rect = CGRect(x: 0, y: 0, width: 100, height: 100) // CGFloat, Double, Int
CGPoint Can be created like this.
let point = CGPoint(x: 0,y :0) // CGFloat, Double, Int
CGSize Can be created like this.
let size = CGSize(width: 100, height: 100) // CGFloat, Double, Int
Also size and point with 0 as the values, it can be done like this.
let size = CGSize.zero // width = 0, height = 0
let point = CGPoint.zero // x = 0, y = 0, equal to CGPointZero
let rect = CGRect.zero // equal to CGRectZero
CGRectZero & CGPointZero replaced with CGRect.zero & CGPoint.zero in Swift 3.0.

Quick fix for CGRectMake , CGPointMake, CGSizeMake in Swift3 & iOS10
Add these extensions :
extension CGRect{
init(_ x:CGFloat,_ y:CGFloat,_ width:CGFloat,_ height:CGFloat) {
self.init(x:x,y:y,width:width,height:height)
}
}
extension CGSize{
init(_ width:CGFloat,_ height:CGFloat) {
self.init(width:width,height:height)
}
}
extension CGPoint{
init(_ x:CGFloat,_ y:CGFloat) {
self.init(x:x,y:y)
}
}
Then go to "Find and Replace in Workspace"
Find CGRectMake , CGPointMake, CGSizeMake and Replace them with CGRect , CGPoint, CGSize
These steps might save all the time as Xcode right now doesn't give us quick conversion from Swift 2+ to Swift 3

In Swift 3, you can simply use CGPoint.zero or CGRect.zero in place of CGRectZero or CGPointZero.
However, in Swift 4, CGRect.zero and 'CGPoint.zero' will work

If you want to use them as in swift 2, you can use these funcs:
For CGRectMake:
func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
return CGRect(x: x, y: y, width: width, height: height)
}
For CGPointMake:
func CGPointMake(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
return CGPoint(x: x, y: y)
}
For CGSizeMake:
func CGSizeMake(_ width: CGFloat, _ height: CGFloat) -> CGSize {
return CGSize(width: width, height: height)
}
Just put them outside any class and it should work. (Works for me at least)

The structures as well as all other symbols in Core Graphics and other APIs have become cleaner and also include parameter names.
https://developer.apple.com/reference/coregraphics#symbols
CGRect(x: Int, y: Int, width: Int, height: Int)
CGVector(dx: Int, dy: Int)
CGPoint(x: Double, y: Double)
CGSize(width: Int, height: Int)
CGPoint Example:
let newPoint = stackMid.convert(CGPoint(x: -10, y: 10), to: self)
CGVector Example:
self.physicsWorld.gravity = CGVector(dx: 0, dy: gravity)
CGSize Example:
hero.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 16, height: 18))
CGRect Example:
let back = SKShapeNode(rect: CGRect(x: 0-120, y: 1024-200-30, width: 240, height: 140), cornerRadius: 20)
Apple Blog
Swift syntax and API renaming changes in Swift 3 make the language feel more natural, and provide an even more Swift-y experience when calling Cocoa frameworks. Popular frameworks Core Graphics and Grand Central Dispatch have new, much cleaner interfaces in Swift.

Swift 3 Bonus: Why didn't anyone mention the short form?
CGRect(origin: .zero, size: size)
.zero instead of CGPoint.zero
When the type is defined, you can safely omit it.

Try the following:
var myToolBar = UIToolbar.init(frame: CGRect.init(x: 0, y: 0, width: 320, height: 44))
This is for the swift's latest version

You can use this with replacement of CGRectZero
CGRect.zero

For CGSize
CGSize(width: self.view.frame.width * 3, height: self.view.frame.size.height)

Instead of CGSizeMake add CGSize it will work.
CGSizeMake is used in objective c.
you don't want to use make with swift

In Swift 4 it works like below
collectionView.setContentOffset(CGPoint.zero, animated: true)

Related

How to add corner smoothing to UIImageView?

I have an image with which I perform editing actions
now I'm trying to make the logic of smoothing the edges just for the picture, not for the imageView
the user must pass a value with which the edges of the image should be smoothed
I tried to use this code but it doesn't work for me
func image(withRoundedCornersRadius radius: CGFloat) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIBezierPath(roundedRect: rect, cornerRadius: CGFloat(radius)).addClip()
draw(in: rect)
let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return roundedImage
}

Migration from Swift 3 to Swift 4 Navigation Bar broken interface

I have migrated my app from Swift 3.1 to Swift 4.0 (Xcode 8.3.3 to Xcode 9.0) and some part of my interface is broken now. Navigation Bar of Navigation controller is complete mess. Please, look at screenshot:
There are 3 elements:
left Netfnet logo (image)
right Signal strength (image)
right QR Code button
As you can see, two images are too big and not in center and button was deformed (it should be perfect square, all images too).
There is code which generated navigation controller:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
settings()
}
func settings() {
let color = UIColor(red: 81 / 255, green: 155 / 255, blue: 22 / 255, alpha: 1.0)
self.navigationController?.navigationBar.barTintColor = color
let logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
logoImageView.contentMode = .scaleAspectFit
let logo = UIImage(named: "littleLogoImage")
logoImageView.image = logo
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: logoImageView)
let signalStengthImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
signalStengthImageView.contentMode = .scaleAspectFit
signalStengthImageView.image = UIImage(named: "signalStrength4")
let signalStengthImageItem = UIBarButtonItem(customView: signalStengthImageView)
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "qrCodeButton"), for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
let qrCodeButtonItem = UIBarButtonItem(customView: button)
navigationItem.rightBarButtonItems = [qrCodeButtonItem, signalStengthImageItem] //
}
}
I can decrease resolution of images directly myself, but I just don't get why everting was fine in Swift 3.1 and in Swift 4.0 is broken.
I will be thankful for any help or advice.
You have to add width and height constraints.
Your barImageView and barButton in CustomNavigationController should be like below :
func barImageView(imageName: String) -> UIBarButtonItem {
let imgView = imageView(imageName: imageName)
let widthConstraint = imgView.widthAnchor.constraint(equalToConstant: 35)
let heightConstraint = imgView.heightAnchor.constraint(equalToConstant: 35)
heightConstraint.isActive = true
widthConstraint.isActive = true
return UIBarButtonItem(customView: imgView)
}
func barButton(imageName: String, selector: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: imageName), for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
button.addTarget(self, action: selector, for: .touchUpInside)
let widthConstraint = button.widthAnchor.constraint(equalToConstant: 35)
let heightConstraint = button.heightAnchor.constraint(equalToConstant: 35)
heightConstraint.isActive = true
widthConstraint.isActive = true
return UIBarButtonItem(customView: button)
}
Your signalStengthImageView in LogoWithSignalStrength:
signalStengthImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
signalStengthImageView.contentMode = .scaleAspectFit
let widthConstraint = signalStengthImageView.widthAnchor.constraint(equalToConstant: 35)
let heightConstraint = signalStengthImageView.heightAnchor.constraint(equalToConstant: 35)
heightConstraint.isActive = true
widthConstraint.isActive = true
In Xcode 9, Navigation bar items are constraints base, Add this:
if #available(iOS 11.0, *) {
logoImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
logoImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
} else {
//set frames
}

Init NSViewController without nib

https://stackoverflow.com/a/28334583/4107801
I tried the method mentioned in this answer but it crashes with bad access every time.
Maybe the private APIs have changed or I'm simply implementing it incorrectly. Here is my implementation:
override func loadView() {
view.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 1000, height: 1000))
//view = self.view
splitView = NSSplitView(frame: view.frame)
splitView?.autoresizingMask = .ViewWidthSizable | .ViewHeightSizable
splitView?.setPosition(300, ofDividerAtIndex: 0)
view.addSubview(splitView!)
}
LoadView doesn't init the contentView in the controller so you have to do that manually too.
Adding
view = NSView(frame:CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 1000, height: 1000)))
solved the problem.

Why is UIBarButtonItem image always fuzzy/blurry/pixelated

Here is my current code:
var reply = UIBarButtonItem(image: UIImage(named: "reply"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("reply:"))
self.navigationItem.rightBarButtonItem = reply
The button in the top right corner is always fuzzy. This is a screenshot from an iPhone4s device so it is not a retina-related issue.
I have tried different image sizes ranging from 30x30 to 512x512 and adding the image using customView. These methods have not fixed the issue.
Thanks in advance.
I have solved it using this method:
var replyBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
replyBtn.setImage(UIImage(named: "reply"), forState: UIControlState.Normal)
replyBtn.addTarget(self.navigationController, action: Selector("reply:"), forControlEvents: UIControlEvents.TouchUpInside)
var item = UIBarButtonItem(customView: replyBtn)
self.navigationItem.rightBarButtonItem = item
It displays a very crisp button using the exact same image.
From IOS human interface guide the icon should be 22x22
Take a look at the documentation here:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/BarIcons.html
Try this:
func createBarButton(image: String, size: CGSize, offset: (x: CGFloat, y: CGFloat) = (0,0), hightlightable: Bool = true, action: Selector) -> UIBarButtonItem {
let btn = UIButton(type: .custom)
let img = UIImage(named: image)
btn.setBackgroundImage(img, for: .normal)
btn.addTarget(self, action: action, for: .touchUpInside)
btn.frame = CGRect(x: offset.x, y: offset.y, width: size.width, height: size.height)
btn.adjustsImageWhenHighlighted = hightlightable
let view = UIView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
// view.bounds = view.bounds.offsetBy(dx: offset.x, dy: offset.y)
view.addSubview(btn)
let barButton = UIBarButtonItem(customView: view)
return barButton
}
self.navigationItem.rightBarButtonItem = createBarButton(image: "YOUR_IMAGE",
size: CGSize(width: 35, height: 35),
offset: (x: -10, y: 0),
action: #selector(showXY))

CABasicAnimation in Swift Playground

Been going nuts trying to get a live view of an animation in a Swift Playground like in the WWDC "Swift Playgrounds" video. I tried to do a UIView.animateWithDuration with no luck so I am now trying to do a CABasicaAnimation because this seems to be what was used in the demo. I'be gotten rid of a lot of confusing errors and have imported the proper frameworks but am still having no luck getting my little circle to do anything but sit still in the center of my XCPShowView. Here is my code:
import Foundation
import XCPlayground
import UIKit
import QuartzCore
//Circle Button
class timerButtonGraphics: UIView {
override func drawRect(rect: CGRect) {
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
var bounds = self.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2
center.y = bounds.origin.y + bounds.size.height / 2
var radius = 61
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.strokeWithBlendMode(kCGBlendModeNormal, alpha: 100)
path.lineWidth = 5
colorGreen.setStroke()
path.stroke()
//Define the animation here
var anim = CABasicAnimation()
anim.keyPath = "scale.x"
anim.fromValue = 1
anim.toValue = 100
anim.delegate = self
self.layer.addAnimation(anim, forKey: nil)
}
}
var test = timerButtonGraphics(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
test.setTranslatesAutoresizingMaskIntoConstraints(true)
XCPShowView("Circle Animation", test)`
The first part of the solution is to enable the Run in Full Simulator option. See this answer for a step-by-step.
The second part of the solution is to contain your animated view in a container view, e.g.:
let container = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
XCPShowView("Circle Animation", container)
let test = timerButtonGraphics(frame: CGRect(x: 198, y: 0, width: 4, height: 400))
container.addSubview(test)
The third part of the solution is to correct your animation. The keyPath should be transform.scale.x instead of scale.x and you need to add a duration, e.g.:
anim.keyPath = "transform.scale.x"
anim.duration = 5
You should then be able to view the animation in your playground.

Resources