iOS blur effect to ImageView with Swift - ios

I am trying to make simple iOS app. I need to make image view with blur effect.
I found this code on Stack Overflow:
class BlurImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
}
required init(coder aDecoder: NSCoder!){
super.init(coder: aDecoder)
var blur:UIBlurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light)
var effectView:UIVisualEffectView = UIVisualEffectView (effect: blur)
effectView.frame = frame
addSubview(effectView)
}
}
And I need to connect this class to my image_view, but I don't know how to do it.
I try to do it in my view_did_load function in my ViewController (image_view is a outlet)
override func viewDidLoad() {
super.viewDidLoad()
image_view = BlurImageView()
}
but NSCoder required... What is it? maybe my way is a wrong way?

You don't need it. The reason why you're not seeing results is because you're attempting to initialize the class from a different initializer than the one you setup.
Try:
class BlurImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
}
override init() {
var blur:UIBlurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light)
var effectView:UIVisualEffectView = UIVisualEffectView (effect: blur)
effectView.frame = frame
addSubview(effectView)
}
}

You need to make your image_view an instance of BlurImageView, so in your view controller and where your image_view is an outlet, you need to make it an instance of BlurImageView and not an instance of an UIImageView.

Related

Subclassed view's uiimage not appearing as IBDesignable

I have set up a subclassed UIView, and want to see the embedded image in IB - so I've set it as IBDesignable
#IBDesignable
class DieView: UIView {
#IBInspectable
var dieImage : UIImage = UIImage()
override init(frame: CGRect) {
super.init(frame: frame)
updateLayout()
}
convenience init() {
self.init(frame: CGRect.zero)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
updateLayout()
}
// for IB
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
updateLayout()
}
func updateLayout() {
self.backgroundColor = .red
let profileImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height))
profileImageView.image = UIImage(named: "dice1")
profileImageView.contentMode = .scaleAspectFit
profileImageView.layer.masksToBounds = false
self.addSubview(profileImageView)
}
func showNumber(number: Int) {
}
}
The background colour changes, but the embedded image doesn't update. Why not?
From the documentation of the prepareForInterfaceBuilder():
Interface Builder waits until all objects in a graph have been created
and initialized before calling this method. So if your object’s
runtime configuration relies on subviews or parent views, those
objects should exist by the time this method is called.
which says that subviews should exist before this method is called. I'm not sure, but try to add image view before this is called. Also, you have to keep in mind that prepareForInterfaceBuilder() is called independently by interface builder. Read the docs for more info. Good Luck!

Changing variables of a custom UIView in another custom ViewController

I know it may be the basic question but I am new to Swift.
Also, I have tried various solutions on SO but could not resolve the issue.
So if anyone can help me with my problem.
I have a custom UIVIEW class as follows:
class SearchTextFieldView: UIView, UITextFieldDelegate{
public var searchText = UITextField()
override init(frame: CGRect) {
super.init(frame: frame)
initializeUI()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initializeUI()
}
func initializeUI() {
searchText.placeholder = "Enter model no"
searchText.backgroundColor = UIColor.white
searchText.textColor = UIColor.darkGray
searchText.layer.cornerRadius = 5.0
searchText.delegate=self
self.addSubview(searchText)
}
override func layoutSubviews() {
searchText.frame = CGRect(x: 20.0, y: 5.0, width: self.frame.size.width - 40,height : self.frame.size.height - 10)
}
}
Now I want to set text to SearchText textfield from another class which is as follows:
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
// Do any additional setup after loading the view.
}
func setupUI() {
let searchTextFieldView = SearchTextFieldView()
self.view.addSubview(searchTextFieldView) //adding view containing search box view at the top
**searchTextFieldView.searchText.text = "My Text"**
}
I am using Storyboard. Also, I can see the textfield with placeholder text.only problem is I can not set text to it.
Can anybody help. Whats wrong in my code.
It is needed to call searchTextFieldView.setNeedsDisplay(), this will in turn call override func draw(_ rect: CGRect) in class SearchTextFieldView.
Add override func draw(_ rect: CGRect) {} in SearchTextFieldView, and try setting searchText.text = <someValue> in draw(). You can use a String property in SearchTextFieldView, to get <someValue> from the client (one who is using SearchTextFieldView) class.
You are creating you view via SearchTextFieldView(), while you have 2 available initializers init(frame:) and init?(coder:).
If you change
let searchTextFieldView = SearchTextFieldView()
with
let searchTextFieldView = SearchTextFieldView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
you will see the text.
You are not setting frame to the view. Also you are not loading the .xib in the view class. It should be like:-
class SearchTextFieldView: UIView, UITextFieldDelegate{
//MARK:- Initializer
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize(withFrame: self.bounds)
}
override init(frame : CGRect) {
super.init(frame: frame)
initialize(withFrame: frame)
}
//MARK: - View Initializers
func initialize(withFrame frame : CGRect) {
Bundle.main.loadNibNamed("SearchTextFieldView", owner: self, options: nil)
view.frame = frame
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addSubview(view)
initializeUI()
}
}
Now you can call the below code in view controller:-
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
// Do any additional setup after loading the view.
}
func setupUI() {
let searchTextFieldView = SearchTextFieldView(frame: ?*self.view.bounds)
self.view.addSubview(searchTextFieldView)
//adding view containing search box view at the top
searchTextFieldView.searchText.text = "My Text"
}
Don't forget to create an xib with name "SearchTextFieldView.xib" as you are loading that nib in your initialize function.
Hope it helps :)
add frame for the searchTextFieldView inside setupUI() method. because the View got loaded on the view but its doesn't have a frame (x,y position, width and height). Change your UIViewController's colour to grey and u can see the your view loaded on the left corner (0,0). set frame size for the view that will solve this problem.

A Expected Declaration Error when trying to assign a text to label

I'm trying to create a label class which contain other labels.
here is my code
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
class mainLabel: UILabel{
var top: UILabel! = UILabel()
top.text = "text" //*Expected declaration error
var down: UILabel! = UILabel()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
There are several issues with your code. The error you receive is because you can only declare variables or functions in a class scope and using top.text you're trying to modify an instance property of the class outside the function scope, which is not allowed.
Secondly, you shouldn't declare a class inside a function that rarely makes sense.
Lastly, don't declare anything as an implicitly unwrapped optional (UILabel!) if you're assigning a value to it right away.
There are several ways to create a reusable UI element that consists of 2 UILabel and can be created programatically. You can subclass a UIStackView to handle the layout automatically or if you want more control, you could simply subclass UIView, add the 2 UILabels as subViews and handle the layout by adding Autolayout constraints programatically.
Here's a solution using a UIStackView subclass. Modify any properties to fit your exact needs, this is just for demonstration.
class MainLabel: UIStackView {
let topLabel = UILabel()
let bottomLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
axis = .vertical
distribution = .fillEqually
addArrangedSubview(topLabel)
addArrangedSubview(bottomLabel)
topLabel.textColor = .orange
topLabel.backgroundColor = .white
bottomLabel.textColor = .orange
bottomLabel.backgroundColor = .white
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Test in a Playground:
PlaygroundPage.current.needsIndefiniteExecution = true
let mainLabel = MainLabel(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
PlaygroundPage.current.liveView = mainLabel
mainLabel.topLabel.text = "Top"
mainLabel.bottomLabel.text = "Bottom"

Custom UIView without Storyboard

Now I'm practicing build IOS app without using storyboard , but I have a problem want to solve , I created a custom UIView called BannerView and added a background(UIView) and a title(UILabel) , and called this BannerView in the MainVC , but run this app , it crashes at the function setupSubviews() and I don't know why.
import UIKit
import SnapKit
class BannerView: UIView {
var background: UIView!
var title: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
setupSubviews()
}
convenience init() {
self.init(frame: CGRect.zero)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupSubviews()
}
func setupSubviews() {
background.backgroundColor = .gray
title.text = "INHEART"
self.addSubview(background)
self.addSubview(title)
}
override func layoutSubviews() {
background.snp.makeConstraints { make in
make.width.equalTo(ScreenWidth)
make.height.equalTo(BannerHeight)
make.left.top.right.equalTo(0)
}
title.snp.makeConstraints { make in
make.width.equalTo(100)
make.center.equalTo(background.snp.center)
}
}
}
class MainVC: UIViewController {
var bannerView:BannerView!
override func viewDidLoad() {
super.viewDidLoad()
bannerView = BannerView(frame: CGRect.zero)
view.addSubview(bannerView)
}
}
Your properties do not appear to be initialised
var background: UIView!
var title: UILabel!
You should initialize these in your init method
self.background = UIView()
self.title = UILabel()
If you use force unwrapping on a class property you must initialize in the init method. XCode should be complaining to you about this and your error message should show a similar error
You are not initialised the background view please initialised them
self.background = UIView()
self.title = UILabel()
and if you want to create custom view by use of xib the follow them Custum View
You must have to initialised the self.background = UIView() and self.title = UILabel() first.
You can initalised them in setupSubviews() function before the set/assign values to them.

Setting a UIImageView to an initial state of blurred

I'm attempting to initially blur a background image on a UIViewController. When an #IBAction is called, I'd like to unblur backgroundImage. I can get the image to initially blur, but I can't get rid of the blur if I initially blur it. However, if I don't initially blur backgroundImage, my method works as desired by toggling between a blurred and unblurred image.
These are the relevant variables on my UIViewController class.
#IBOutlet weak var backgroundImage: UIImageView!
// I also leave this hanging around so I can add/remove it as needed
var blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
When the view loads, I'd initially like backgroundImage to have a UIVisualEffectView over it. I initially tried to call toggleBlurView in viewDidLoad, but the display of the UIBlurEffect was off, so I added the code for toggleBlurView in viewDidLayoutSubviews, which fixed that problem.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// if I comment this out, the toggleBlurView() method works as desired
toggleBlurView()
}
Here's my toggleBlurView method.
func toggleBlurView() {
// if there's a blurView, remove it...
if blurView.isDescendant(of: backgroundImage) {
blurView.removeFromSuperview()
}
// otherwise, add blurView to backgroundImage
else {
blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
blurView.frame = backgroundImage.bounds
backgroundImage.addSubview(blurView)
}
}
I have an #IBAction that, when called, also runs the toggleBlurView method.
#IBAction func playFrequency(_ sender: UIButton) {
// do stuff
toggleBlurView()
}
My code does not crash, but I can't get the desired results. I'm not sure if I've found a bug or I'm doing something wrong. I'm wagering the latter. Thank you for reading and I welcome suggestions how to set an image to an initial state of blurred.
I got the following code working as you want it to. I changed up the toggleBlurView function so it's a little more flexible, but this shouldn't affect the functionality.
//
// ViewController.swift
// tableviewheader-test
//
// Created by Forest Kunecke on 3/29/17.
// Use this code for freeeeee!!!! Free as in free beer!!
//
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myImage: UIImageView!
var blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
override func viewDidLoad() {
super.viewDidLoad()
toggleBlurView(myImage)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func toggleBlur(_ sender: Any) {
toggleBlurView(myImage)
}
func toggleBlurView(_ imageView: UIImageView) {
// if there's a blurView, remove it...
if blurView.isDescendant(of: imageView) {
blurView.removeFromSuperview()
}
// otherwise, add blurView to backgroundImage
else {
blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
blurView.frame = imageView.bounds
imageView.addSubview(blurView)
}
}
}
Here is a screenshot of my storyboard:

Resources