image and string in same label in swift 2 - ios

I have image and string in label togher in navigation bar
When I use coins, say use all 50 of them it should be 0 with image coins but its not
but when I click to another viewcontroller and back to same viewcontroller with coins the image is back
here is code:
let coinLabel = UILabel()
override func viewWillAppear(animated: Bool) {
// Set icon in label in navigation bar ////
let image = UIImage(named: "coins.jpeg")
let newSize = CGSize(width: 15, height: 15)
//Resize image
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let imageResized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//Create attachment text with image
let attachment = NSTextAttachment()
attachment.image = imageResized
let attachmentString = NSAttributedString(attachment: attachment)
let myString = NSMutableAttributedString(string: "\(coins)")
myString.appendAttributedString(attachmentString)
coinLabel.attributedText = myString
coinLabel.sizeToFit()
// Set defined label to navigation bar right corner
let leftItem = UIBarButtonItem(customView: coinLabel)
self.navigationItem.rightBarButtonItem = leftItem
coinLabel.font = coinLabel.font.fontWithSize(15)
}
I think the problem is with reloading... or something. Any Idea??

Don't sure that it's a reason but at least you need to set font before calling sizeToFit()
coinLabel.font = coinLabel.font.fontWithSize(15)
coinLabel.sizeToFit()
Also you missed call to super.viewWillAppear(animated)

Related

Swift 5: Better way/approach to add image border on photo editing app?

In case the title doesn't make sense, i'm trying to make a photo editing app where user can add border to their photo. For now, i'm testing a white border.
here is a gif sample of the app. (see how slow the slider is. It's meant to be smooth like any other slider.)
Gif sample
My approach was, to render the white background to the image's size, and then render the image n% smaller to shrink it hence the border.
But i have come to a problem where when i'm testing on my device (iphone 7 plus) the slider was so laggy and slow as if it's taking so much time to compute the function.
Here are the codes for the function. This function serves as blend the background with the foreground. Background being plain white colour.
blendImages is a function located on my adjustmentEngine class.
func blendImages(backgroundImg: UIImage,foregroundImg: UIImage) -> Data? {
// size variable
let contentSizeH = foregroundImg.size.height
let contentSizeW = foregroundImg.size.width
// the magic. how the image will scale in the view.
let topImageH = foregroundImg.size.height - (foregroundImg.size.height * imgSizeMultiplier)
let topImageW = foregroundImg.size.width - (foregroundImg.size.width * imgSizeMultiplier)
let bottomImage = backgroundImg
let topImage = foregroundImg
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width : contentSizeW, height: contentSizeH))
let imgView2 = UIImageView(frame: CGRect(x: 0, y: 0, width: topImageW, height: topImageH))
// - Set Content mode to what you desire
imgView.contentMode = .scaleAspectFill
imgView2.contentMode = .scaleAspectFit
// - Set Images
imgView.image = bottomImage
imgView2.image = topImage
imgView2.center = imgView.center
// - Create UIView
let contentView = UIView(frame: CGRect(x: 0, y: 0, width: contentSizeW, height: contentSizeH))
contentView.addSubview(imgView)
contentView.addSubview(imgView2)
// - Set Size
let size = CGSize(width: contentSizeW, height: contentSizeH)
UIGraphicsBeginImageContextWithOptions(size, true, 0)
contentView.drawHierarchy(in: contentView.bounds, afterScreenUpdates: true)
guard let i = UIGraphicsGetImageFromCurrentImageContext(),
let data = i.jpegData(compressionQuality: 1.0)
else {return nil}
UIGraphicsEndImageContext()
return data
}
Below are the function i called to render it into uiImageView
guard let image = image else { return }
let borderColor = UIColor.white.image()
self.adjustmentEngine.borderColor = borderColor
self.adjustmentEngine.image = image
guard let combinedImageData: Data = self.adjustmentEngine.blendImages(backgroundImg: borderColor, foregroundImg: image) else {return}
let combinedImage = UIImage(data: combinedImageData)
self.imageView.image = combinedImage
This function will get the image and blend it with a new background colour for the border.
And finally, below are the codes for the slider's didChange function.
#IBAction func sliderDidChange(_ sender: UISlider) {
print(sender.value)
let borderColor = adjustmentEngine.borderColor
let image = adjustmentEngine.image
adjustmentEngine.imgSizeMultiplier = CGFloat(sender.value)
guard let combinedImageData: Data = self.adjustmentEngine.blendImages(backgroundImg: borderColor, foregroundImg: image) else {return}
let combinedImage = UIImage(data: combinedImageData)
self.imageView.image = combinedImage
}
So the question is, Is there a better way or optimised way to do this? Or a better approach?

Swift iOS -How to Set NSTextAttachment Content Mode to Aspect Fit?

I have a PDF image that I appended to a String. I used NSTextAttachment and NSAttributedString to get it done. I add them to a textView and the result is Hello with an image of the World underneath of it.
The problem is when I set the bounds for the PDF image on the textAttachment the World image is distorted. It's stretched long and wide.
How can I set a contentMode on the textAttachment object to redraw the image correctly using .aspectRatio?
number #4 is where I set the bounds
// #1. Define dict attribute for string
let bold17 = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 17)]
// #2. Create "hello" string and add the dict attribute to it
let helloStr = NSAttributedString(string: "Hello\n\n", attributes: bold17)
// #3. Create NSTextAttachment
let textAttachment = NSTextAttachment()
// #4. Add image to the textAttachment then set it's bounds
textAttachment.image = UIImage(named: "world_PDF")
textAttachment.bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
// #5. Set image as NSAttributedString
let worldImage = NSAttributedString(attachment: textAttachment)
// #6. Create NSMutableString to
let mutableAttributedString = NSMutableAttributedString()
// #7. Append the "hello" string and the "world" image to each other using the mutableAttributedString object
mutableAttributedString.append(helloStr)
mutableAttributedString.append(worldImage)
// #8. Set the mutableAttributedString to the textView then center it
textView.attributedText = mutableAttributedString
textView.textAlignment = .center
I followed #Maciej Swic's answer
Resize NSTextAttachment Image
For some reason I couldn't extend the NSTextAttachment class so I added it to the bottom of the class I was using it in. I removed the bounds property that I used in my question and used his function instead. It's on #4, the second line:
class MyController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
// #1. Define dict attribute for string
let bold17 = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 17)]
// #2. Create "hello" string and add the dict attribute to it
let helloStr = NSAttributedString(string: "Hello\n\n", attributes: bold17)
// #3. Create NSTextAttachment
let textAttachment = NSTextAttachment()
// #4. Add image to the textAttachment then set it's bounds
textAttachment.image = UIImage(named: "world_PDF")
textAttachment.setImageHeight(height: 200) // <----HIS ANSWER HERE
// #5. Set image as NSAttributedString
let worldImage = NSAttributedString(attachment: textAttachment)
// #6. Create NSMutableString to
let mutableAttributedString = NSMutableAttributedString()
// #7. Append the "hello" string and the "world" image to each other using the mutableAttributedString object
mutableAttributedString.append(helloStr)
mutableAttributedString.append(worldImage)
// #8. Set the mutableAttributedString to the textView then center it
textView.attributedText = mutableAttributedString
textView.textAlignment = .center
}
}
extension NSTextAttachment {
func setImageHeight(height: CGFloat) {
guard let image = image else { return }
let ratio = image.size.width / image.size.height
bounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: ratio * height, height: height)
}
}

Change background color of UITabBarItem in Swift [duplicate]

This question already has answers here:
UITabBar change background color of one UITabBarItem on iOS7
(6 answers)
Closed 5 years ago.
I just want to change the background colour of one of the tab bat items. I found many links but didn't get any help from that.
Requirement:
And, this is the way I setup my tab bar items
let myTabBarItem3 = (self.tabBar.items?[2])! as UITabBarItem
myTabBarItem3.image = UIImage(named: "ic_center")?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
myTabBarItem3.selectedImage = UIImage(named: "ic_center")?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
What I want is the black colour background for centre tab bar item.
Any idea?
And yes it is not a duplicate, Because the previous answered are not accurate and to add extra subview is never a good option, So expecting some good solution from friends
If you want to change the background colour of only centre tabBarItem you can follow below code.
NOTE: All the below code is used in a custom class which extends UITabBarController as:
class tabbarVCViewController: UITabBarController, UITabBarControllerDelegate {
// MARK: - ViewController Override Methods.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupInitilView()
}
// MARK: - setup Initial View Methode.
private func setupInitilView() {
delegate = self
// Sets the default color of the icon of the selected UITabBarItem and Title
UITabBar.appearance().tintColor = UIColor.white
// Sets the default color of the background of the UITabBar
UITabBar.appearance().barTintColor = UIColor.white
// Sets the background color of the selected UITabBarItem (using and plain colored UIImage with the width = 1/5 of the tabBar (if you have 5 items) and the height of the tabBar)
//UITabBar.appearance().selectionIndicatorImage = UIImage().makeImageWithColorAndSize(color: UIColor.black, size: CGSize.init(width: tabBar.frame.width/4, height: tabBar.frame.height))
// Uses the original colors for your images, so they aren't not rendered as grey automatically.
for item in self.tabBar.items! {
if let image = item.image {
//item.image = image.withRenderingMode(.alwaysTemplate)
item.image = image.withRenderingMode(.alwaysOriginal) //Use default image colour as grey colour and your centre image default colour as white colour as your requirement.
}
}
//Change the backgound colour of specific tabBarItem.
let itemIndex:CGFloat = 2.0
let bgColor = UIColor.black
let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRect.init(x: itemWidth * itemIndex, y: 0, width: itemWidth, height: tabBar.frame.height))
bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, at: 0)
}
// MARK: - UITabbarController Override Methods .
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
}
// MARK: - UITabBarControllerDelegate Methods
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
return true
}
}
Use tabBarItem images default colour as grey according to your UI and centre tabBarItem image default colour as white colour in Asset.
And you will want to extend the UIImage class to make the plain colored image with the size you need:
extension UIImage {
func makeImageWithColorAndSize(color: UIColor, size: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect.init(x: 0, y: 0, width: size.width, height: size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
You can add a subview to the parent tabBar
Then you can set a background color on the subview.
Calculating the offset and width of your tabBarItem and inserting the subView under it.
let itemIndex = 2
let bgColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1.0)
let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRectMake(itemWidth * itemIndex, 0, itemWidth, tabBar.frame.height))
bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, atIndex: 0)
Try this :
UITabBar.appearance().tintColor = UIColor.pink
UITabBar.appearance().barTintColor = UIColor.white
if #available(iOS 10.0, *) {
UITabBar.appearance().unselectedItemTintColor = UIColor.white
} else {
// Fallback on earlier versions
}
let x = Double(UIScreen.main.bounds.width / 5.0)
let y = Double(tabBarController!.tabBar.frame.size.height)
let indicatorBackground: UIImage? = self.image(from: UIColor.black, for: CGSize(width: x, height: y))
UITabBar.appearance().selectionIndicatorImage = indicatorBackground
Helper Methods
func image(from color: UIColor, for size: CGSize) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
autoreleasepool {
UIGraphicsBeginImageContext(rect.size)
}
let context: CGContext? = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
You can use imageView to achieve this affect , try this approach
let myImageView: UIImageView = {
let imageView = UIImageView()
return imageView
}()
// Now add this imageView as subview and apply constraints
tabbar.addSubview(myImageView)
myImageView.translatesAutoresizingMaskIntoConstraints = false
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[v0(28)]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": myImageView]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[v0(28)]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": myImageView]))
tabbar.myImageView.image = UIImage(named: "ic_center")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
tabbar.myImageView.tintColor = UIColor.black

Why is my left view in text field not working?

I've added a left view to my text field using the code below:
usernameField.leftViewMode = UITextFieldViewMode.always
passwordField.leftViewMode = UITextFieldViewMode.always
let usernameImageView = UIImageView()
let usernameImage = UIImage(named: "user icon grey.png")
usernameImageView.image = usernameImage
usernameField.leftView = usernameImageView
let passwordImageView = UIImageView()
let passwordImage = UIImage(named: "lock icon grey.png")
passwordImageView.image = passwordImage
passwordField.leftView = passwordImageView
This didn't work, I then added a UIDesignable, a very neat process that I took from this question below on StackOverflow. This means that I can see the icons in the storyboard, as can be seen below. However, this doesn't show up.
Swift add icon/image in UITextField
The problem is with how you create the image view. You first create an empty image view which then has no size. You then assign the image to the image view but this does not automatically resize the image view.
There are two solutions.
Tell the image view to resize itself after assigning the image.
let usernameImageView = UIImageView()
let usernameImage = UIImage(named: "user icon grey.png")
usernameImageView.image = usernameImage
usernameImageView.sizeToFit()
Create the image view with the image. This is simpler approach.
let usernameImage = UIImage(named: "user icon grey.png")
let usernameImageView = UIImageView(image: usernameImage)
The problem is with your code. using this code now your left view in textField is working.
#IBOutlet weak var name: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
usernameField.leftViewMode = .always
let usernameImageView = UIImageView()
usernameImageView.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
let usernameImage = (your image name)
usernameImageView.image = usernameImage
usernameField.leftView = usernameImageView

Taking a screenshot and adding a text/watermark on top in Swift

Im trying to allow the ability for a user to share a screenshot of an App and share it. I have got the taking of a screenshot and sharing but was interested in finding out if anyone knew how to add a layer of text on top of that screenshot when it is being taken, kind of like a watermark.
Here I take the screenshot:
let layer = UIApplication.sharedApplication().keyWindow!.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.renderInContext(UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let croppedImage = self.cropImage(screenshot)
let activityViewController = UIActivityViewController(activityItems: [croppedImage], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
I crop the screenshot image in this function so it just shows middle of screen:
func cropImage(screenshot: UIImage) -> UIImage {
let scale = screenshot.scale
let imgSize = screenshot.size
let screenHeight = UIScreen.mainScreen().bounds.height
let bound = self.view.bounds.height
let navHeight = self.navigationController!.navigationBar.frame.height
let bottomBarHeight = screenHeight - navHeight - bound
let crop = CGRectMake(0, 200, //"start" at the upper-left corner
(imgSize.width - 1) * scale, //include half the width of the whole screen
(imgSize.height - bottomBarHeight - 300) * scale) //include the height of the navigationBar and the height of view
let cgImage = CGImageCreateWithImageInRect(screenshot.CGImage, crop)
let image: UIImage = UIImage(CGImage: cgImage!)
return image
}
Yes it is possible to do that. Try adding subview to your image view like below
let newImageView = UIImageView(image : croppedImage)
let labelView = UILabel(frame: CGRectMake(30, 30, 100, 20)) //adjust frame to change position of water mark or text
labelView.text = "my text"
newImageView.addSubview(labelView)
UIGraphicsBeginImageContext(newImageView.frame.size)
newImageView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let watermarkedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

Resources