delete subview that use with imageView - ios

I have a map picture in my ImageView and I want a red dot for user current location so I use this 3 lines of code for creating red dot above my ImageView
let overlay: UIView = UIView(frame: CGRect(x: xcorIn * 0.822, y: ycorIn * 1.03, width: 5, height: 5))
overlay.backgroundColor = UIColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
imageView.addSubview(overlay)
all I want is after of 2 seconds of red dot appear it must disappear
so I try this
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
self.imageView.delete(overlay)
})
delay function seem work but
self.imageView.delete(overlay)
return me this error
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[UIImageView delete:]:
unrecognized selector sent to instance 0x7f8bef712df0'

You need to remove overlay from the superView. You could either do this:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
overlay.removeFromSuperview()
})
Or if you don´t have overlay globally, you could do this. Add a tag to your overlay and then do this:
let overlay: UIView = UIView(frame: CGRect(x: 100, y: 100, width: 5, height: 5))
overlay.tag = 0
overlay.backgroundColor = UIColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
imageView.addSubview(overlay)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
for subView in self.imageView.subviews {
if subView.tag == 0 {
subView.removeFromSuperview()
}
}
})

You can remove the dot by using its reference and "removeFromSuperview()" method
let overlay: UIView = UIView(frame: CGRect(x: xcorIn * 0.822, y: ycorIn * 1.03, width: 5, height: 5))
overlay.backgroundColor = UIColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
imageView.addSubview(overlay)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
overlay.removeFromSuperview()
})

You are getting that error because there is no delete method in the imageView, but there is a method called removeFromSuperview.
You are going to remove the overlay from the SuperView
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
overlay.removeFromSuperview()
})
Or:
self.overlay.hidden = true
Or try the following if your reference to it was a strong reference, make sure to nil that strong reference:
overlay= nil
Or animate without using dispatchQueue:
UIView.animate(withDuration: 0.5, delay: 0.3, options: [.repeat, .curveEaseOut, .autoreverse], animations: {
self.overlay.alpha = 0
}, completion: nil)

Related

incorrect Navigation bar background image coloring for iphone 12 mini

I'm setting the image of the navigation bar to a gradient. This works perfectly on all models except for iPhone 12 mini.
I've tried calling this on my main view controller in ViewWillAppear, viewDidAppear, and ViewDidLoad
Here's what it looks like on all other models
func setNavGradiant(){
guard let navigationController = self.navigationController else {print("❇️♊️>>>\(#file) \(#line): guard let failed<<<"); return}
let gradientLayer = CAGradientLayer()
var updatedFrame = navigationController.navigationBar.bounds
updatedFrame.size.height += UIApplication.shared.windows[0].windowScene?.statusBarManager?.statusBarFrame.height ?? 0
gradientLayer.frame = updatedFrame
gradientLayer.colors = [ #colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1).cgColor, #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1).cgColor] // start color and end color
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) // vertical gradient start
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.navigationController?.navigationBar.setBackgroundImage(image, for: UIBarMetrics.default)
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor(#colorLiteral(red: 0.9579688907, green: 0.9579688907, blue: 0.9579688907, alpha: 1))]
}
You will probably have better results by subclassing UINavigationController:
class MyNavigationController: UINavigationController {
let gradient = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
gradient.frame = navigationBar.bounds
gradient.colors = [ #colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1).cgColor, #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1).cgColor] // start color and end color
gradient.startPoint = CGPoint(x: 0.5, y: 0.0) // vertical gradient start
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
if let image = getImageFrom(gradientLayer: gradient) {
navigationBar.setBackgroundImage(image, for: UIBarMetrics.default)
}
}
func getImageFrom(gradientLayer:CAGradientLayer) -> UIImage? {
var gradientImage:UIImage?
UIGraphicsBeginImageContext(gradientLayer.frame.size)
if let context = UIGraphicsGetCurrentContext() {
gradientLayer.render(in: context)
gradientImage = UIGraphicsGetImageFromCurrentImageContext()?.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch)
}
UIGraphicsEndImageContext()
return gradientImage
}
}
Try calling:
DispatchQueue.main.async {
self.setNeedsStatusBarAppearanceUpdate()
}
after your setup is done. Should work without dispatching to main thread, but I had previously caught issues of things called from lifecycle methods not being on the main thread. So another thing to check is to make sure you are running the updates on the main thread.

NavBar title hidden behind CAGradientLayer

I would like to add gradient layer to my navbar, but after I add it, layer hides my title, like its behind that new sublayer.
override func viewDidLoad() {
super.viewDidLoad()
self.title = "My Trips"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
//self.navigationController?.navigationBar.layer.addSublayer(gradientLayer)
self.navigationController?.navigationBar.layer.insertSublayer(gradientLayer, at: 1)
setupGradient()
}
let gradientLayer = CAGradientLayer()
func setupGradient() {
gradientLayer.colors = [
UIColor(red: 0.259, green: 0.188, blue: 0.475, alpha: 1).cgColor,
UIColor(red: 0.11, green: 0.024, blue: 0.369, alpha: 1).cgColor
]
gradientLayer.locations = [0, 1]
gradientLayer.startPoint = CGPoint(x: 0.25, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 0.75, y: 0.5)
gradientLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(a: 0, b: 0.58, c: -0.58, d: 0, tx: 0.5, ty: 0))
gradientLayer.bounds = (self.navigationController?.navigationBar.bounds.insetBy(dx: -0.01*view.bounds.size.width, dy: -1*view.bounds.size.height))!
}
Use this line for inserting layer.
self.navigationController?.navigationBar.subviews.first?.layer.insertSublayer(gradientLayer, at: 0)

UIView.animate Ignoring duration on custom pop I created. Swift 5

let bigView = UIViewController()
let pView = UIView()
extension UIViewController {
func showPopUp() {
bigView.modalPresentationStyle = .overFullScreen //or .overFullScreen for transparency
self.present(bigView, animated: false, completion: nil)
let bColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).withAlphaComponent(0.4)
blurView.frame = bigView.view.bounds
blurView.backgroundColor = bColor
bigView.view.addSubview(blurView)
pView.frame = CGRect(x: 0, y: 0, width: 300, height: 180)
if self.traitCollection.userInterfaceStyle == .light {
pView.backgroundColor = #colorLiteral(red: 0.9778117069, green: 0.9778117069, blue: 0.9778117069, alpha: 1) } else {pView.backgroundColor = #colorLiteral(red: 0.2506543464, green: 0.2506543464, blue: 0.2506543464, alpha: 1)}
pView.layer.cornerRadius = 15
pView.isOpaque = false
pView.center = blurView.center
blurView.addSubview(pView)
pView.transform = CGAffineTransform(scaleX: 1, y: 1)
pView.alpha = 0
UIView.animate(withDuration: 0.8, delay: 0.5, options: [], animations: {
pView.alpha = 1
pView.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Hey guys here is a shortened version of my code, not sure why its not animating with a duration... when I click the button I have assigned it just jumps the scale to (scaleX: 1.1, y: 1.1).. instead of gradually animating. Any idea why ?

Custom UI Button not shwing title

I created a custom UI Button class in swift for a follow button, however it is not showing the button title
My code
#IBDesignable
public class GradientButton: UIButton {
override public func layoutSubviews() {
super.layoutSubviews()
layoutGradientButtonLayer()
}
// MARK: Private
private func layoutGradientButtonLayer() {
let layer = UIView()
layer.frame = CGRect(x: 191, y: 257, width: 66.6, height: 24)
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: 66.6, height: 24)
gradient.colors = [
UIColor(red: 0.09, green: 0.85, blue: 0.88, alpha: 1).cgColor,
UIColor(red: 0, green: 0.87, blue: 0.68, alpha: 1).cgColor
]
gradient.locations = [0, 1]
gradient.startPoint = CGPoint(x: 0.78, y: 1)
gradient.endPoint = CGPoint(x: 0.15, y: 1)
self.layer.cornerRadius = 10
self.layer.addSublayer(gradient)
self.clipsToBounds = true
self.setTitle("Follow", for: UIControlState.normal)
}
}
The button appears small width and doesn't have any "Follow" text in it
Change below code you will see title:
self.layer.addSublayer(gradient)
change to
self.layer.insertSublayer(gradient, at: 0)

How to change background color of UITextField to custom gradient color in iOS using Swift

I have done gradient coloring before for changing color of my parent view now I am using same method to change the background color of UITextField but its not working.
This is the method I used for my view:
func setGradientBackgroundOfView()
{
// assigning gradient color to background View
let endingColorOFGradient = UIColor(colorLiteralRed: 133/255, green: 210/255, blue: 230/255, alpha: 1.0).CGColor
let startingColorOfGradient = UIColor(colorLiteralRed: 50/255, green: 189/255, blue: 170/255, alpha: 1.0).CGColor
gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
gradient.colors = [startingColorOfGradient , endingColorOFGradient]
self.view.layer.insertSublayer(gradient, atIndex: 0)
}
And this method for setting layer:
override func viewWillLayoutSubviews() {
gradient.frame = self.view.bounds
}
I am calling my setGradientBackgroundOfView() in viewDidLoad() and it's working perfect but if I change
self.view.layer.insertSublayer(gradient, atIndex: 0)
with
self.textFieldUserName.layer.insertSublayer(gradient, atIndex: 0)
it does not work. What am I missing here?

Resources