Why is UIBarButtonItem image always fuzzy/blurry/pixelated - xcode

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))

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
}

simple fade in function in xcode

despite my best efforts, I am failing on the code for the fade-in timing of my frame. for some reason that I cant understand, the withDuration is not fading at all.
if someone has a moment to review my code I would v much appreciate the help...
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 128, y: 128, width: 256, height: 256))
view.backgroundColor = .red
UIView.animate(withDuration: 3) {
view.alpha = 1
}
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 512, height:
512))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView
containerView.addSubview(view)
Problem 1: view.alpha is already 1 so there is nothing to animate.
Problem 2: Order matters. Things happen in the order you command them. That order must be coherent.
So:
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 512, height: 512))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView
let view = UIView(frame: CGRect(x: 128, y: 128, width: 256, height: 256))
view.alpha = 0
view.backgroundColor = .red
containerView.addSubview(view)
UIView.animate(withDuration: 3) {
view.alpha = 1
}

How to add a link annotation with a PDFActionGoto action type to a PDFPage using swift in MACOS

I have been trying to add a link annotation to my PDFPage so that once clicked it will take me to a specific location of the next page. This is the way I am trying but my code is not working:
The cursor does not change to the pointer style.
Once the area is clicked navigation does not occur.
.freetext annotation is working and getting displayed.
I would appreciate any help regarding this. I have been trying this for the last couple of days. I am using latest version of xcode (12 and swift 5.3)
let docDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let pdfDocument = PDFDocument()
let page1 = PDFPage()
let page2 = PDFPage()
pdfDocument.insert(page1, at: 0)
pdfDocument.insert(page2, at: 1)
let textAnnotation = PDFAnnotation(bounds: NSRect(x: 200, y: 1000, width: 600, height: 25), forType: .freeText, withProperties: nil)
textAnnotation.contents = "Click me to go to the next page"
let linkAnnotation = PDFAnnotation(bounds: NSRect(x: 200, y: 1000, width: 600, height: 25), forType: .link, withProperties: nil)
linkAnnotation.action = PDFActionGoTo(destination: PDFDestination(page: page2, at: NSPoint(x: 200, y: 1000)))
linkAnnotation.shouldDisplay = true
linkAnnotation.shouldPrint = true
let someText = PDFAnnotation(bounds: NSRect(x: 200, y: 1000, width: 600, height: 25), forType: .freeText, withProperties: nil)
someText.contents = "This is the desitnation of link annotation"
page1.addAnnotation(textAnnotation)
page1.addAnnotation(linkAnnotation)
page2.addAnnotation(someText)
let printOpts: [NSPrintInfo.AttributeKey: Any] = [NSPrintInfo.AttributeKey.jobDisposition: NSPrintInfo.JobDisposition.preview, NSPrintInfo.AttributeKey.jobSavingURL: docDirectoryPath]
let printInfo = NSPrintInfo(dictionary: printOpts)
printInfo.horizontalPagination = NSPrintInfo.PaginationMode.automatic
printInfo.verticalPagination = NSPrintInfo.PaginationMode.automatic
printInfo.topMargin = 0.0
printInfo.leftMargin = 0.0
printInfo.rightMargin = 0.0
printInfo.bottomMargin = 0.0
printInfo.isHorizontallyCentered = true
printInfo.isVerticallyCentered = false
printInfo.paperSize = NSSize(width: 8.5*96, height: 11*96)
printInfo.scalingFactor = 1.0
let printOperation = pdfDocument.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: false)!
printOperation.showsPrintPanel = true
printOperation.run()
After much trial and error I figured that if the document is run through printOperation linkAnnotation is not retained. So I used save panel to save document to file instead. If you click on the green area of the first page it will take you to the page 2 (Destination Arrived)
import Foundation
import PDFKit
let page1 = PDFPage()
let page2 = PDFPage()
let link = PDFAnnotation(bounds: NSRect(x: 40, y: 750, width: 200, height: 30), forType: .link, withProperties: nil)
let highlight = PDFAnnotation(bounds: NSRect(x: 40, y: 750, width: 200, height: 30), forType: .highlight, withProperties: nil)
highlight.color = .green
highlight.backgroundColor = .red
let text = PDFAnnotation(bounds: NSRect(x: 40, y: 400, width: 200, height: 30), forType: .freeText, withProperties: nil)
text.contents = "Destination Arrived!"
link.action = PDFActionGoTo(destination: PDFDestination(page: page2, at: NSPoint(x: 40, y: 430)))
page1.addAnnotation(highlight)
page1.addAnnotation(link)
page2.addAnnotation(text)
let pdfDoc = PDFDocument()
pdfDoc.insert(page1, at: 0)
pdfDoc.insert(page2, at: 1)
let savePanel = NSSavePanel()
savePanel.title = NSLocalizedString("Save file", comment: "enableFileMenuItems")
savePanel.nameFieldStringValue = "LinkAnnotation.pdf"
savePanel.prompt = NSLocalizedString("Save", comment: "enableFileMenuItems")
savePanel.allowedFileTypes = ["pdf"]
let fileManager = FileManager.default
savePanel.begin() { (result2) -> Void in
if result2 == NSApplication.ModalResponse.OK {
let fileWithExtensionURL = savePanel.url!
if fileManager.fileExists(atPath: fileWithExtensionURL.path) {
} else {
pdfDoc.write(to: fileWithExtensionURL)
}
}
}

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
}

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

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)

Resources