Swift Custom UIView with init parameters - ios

I have witten a custom UIView class which takes several parameters and overrides an empty storyboard UIView(subclassed as MultiPositionTarget class instead of UIview) as below.The views below are linked as outlet to view controller as it is seen from the code below(in total 9 views).
// Initialize the targets
target1 = MultiPositionTarget(.zero,"targetTemp.png","David","Target")
target1.parentVC = self
targetList.append(target1)
However, it does not accept the parameters. And only loads the view. Here is my class below:
class MultiPositionTarget: UIView{
var targetName: String!
var bottomLabelName: String!
var imageName: String!
var isSelected: Bool!
var labelTop: UILabel!
var labelBottom: UILabel!
var parentVC: SelectTargetViewController!
init(_ frame: CGRect,_ imagName: String,_ targetname: String,_ targetlabel: String){
self.imageName = imagName
self.targetName = targetname
self.bottomLabelName = targetlabel
super.init(frame: frame)
setUp()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
func setUp(){
let viewWidth = self.bounds.width
let viewHeight = self.bounds.height
// Add top label
labelTop = UILabel(frame: CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight/5))
//labelTop.center = CGPoint(x: 160, y: 285)
labelTop.textAlignment = .center
labelTop.font = UIFont(name:"System",size:6)
labelTop.text = self.imageName
labelTop.textColor = UIColor.white
labelTop.backgroundColor = hexStringToUIColor(hex: "#770B2C")
//labelTop.alpha = 0.5
self.addSubview(labelTop)
let image = UIImage(named: "targetTemp.png")
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 0, y: (viewHeight-viewHeight * 4/5), width: viewWidth, height: (viewHeight * 4/5))
self.addSubview(imageView)
// Add bottom Label
labelBottom = UILabel(frame: CGRect(x: 0, y: (viewHeight * 4/5), width: viewWidth, height: viewHeight/5))
//labelBottom.center = CGPoint(x: 160, y: 285)
labelBottom.textAlignment = .center
labelBottom.text = self.bottomLabelName
labelBottom.font = UIFont(name:"System",size:10)
labelBottom.textColor = UIColor.white
labelBottom.backgroundColor = hexStringToUIColor(hex: "770B2C")
labelBottom.alpha = 0.95
self.addSubview(labelBottom)
self.isUserInteractionEnabled = true
let viewTap = UITapGestureRecognizer(target: self, action: #selector(singleTap))
self.addGestureRecognizer(viewTap)
}
}
Any help or hint is appreciated. Thanks in advance stack overflow family.

This line is creating a new view:
target1 = MultiPositionTarget(.zero,"targetTemp.png","David","Target")
The new view is unrelated to the view shown on the screen. The new view isn't actually on the screen at all, because you haven't added it to the view hierarchy. Even if you did, it's invisible because it has a frame of zero.
In short, you can't call your custom initialiser and also design your view in the storyboard. You can initialise the properties you want either in the storyboard as well, or in code.
If you want to initialise the properties in the storyboard as well, you can modify imageName, bottomLabelName and targetName with #IBInsepctable:
#IBInsepctable var targetName: String!
#IBInsepctable var bottomLabelName: String!
#IBInsepctable var imageName: String!
// or, if you want to directly select an image from the storyboard:
// #IBInsepctable var image: UIImage!
This way those properties will show up in the property inspector in the storyboard.
If you want to initialise it in code, you must set it with assignment statements, and not with an initialiser:
target1.targetName = "David"
target1.bottomLabelName = "Target"
target1.imageName = "targetTemp.png"
target1.parentVC = self
targetList.append(target1)

Related

CGRect function is not working while placing image in textfield

I am trying to set image inside the textfield , and for that i am creating an image view in code but when i am trying to adjust its width and height via CGRect(x:int, y:int, width:int, height:int) , its not being applied and the image size is still original. I ve seen so many tutorials for putting image in text field and all of them are using CGRect and its working for them, as size of image gets what they apply in CGRect, but not for me. Below is the code i m trying to use. Image is also attached. Textfield style is rounded (Default) and icon size is 50px.
UIViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var email: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
update()
// Do any additional setup after loading the view.
}
func update() {
email.leftViewMode = .always
let imageview = UIImageView()
let image = UIImage(named: "icon")
imageview.image = image
imageview.frame = CGRect(x: 15, y: 0, width: 50 , height: 50)
email.leftView = imageview
}
}
Also, i ve tried to change 'Render as' to 'template' in image assets but its still not working.
Hey I’ve tried to do it programmatically and it works for me. Quickly drafted it on iPad playgrounds. Try this:
class Test: UIViewController {
let lable = UITextField()
let image = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
lable.frame = CGRect(x: 200, y: 200, width: 300 , height: 50)
lable.backgroundColor = .black
update()
self.view.addSubview(lable)
}
func update() {
lable.leftViewMode = .always
let imageview = UIImageView()
let image = UIImage(systemName: "icloud")
imageview.image = image
imageview.frame = CGRect(x: 15, y: 0, width: 50 , height: 50)
lable.leftView = imageview
self.view.addSubview(imageview)
}
}

Size of image inside textfield is not resizing

I have a custom text field and i want to place image on its left side, but when ever i am running the app, the size of image is not adjusting , i.e its full scale and not taking the width and height being provided. The code and pictures are attached
ViewController class:(In which text field is present)
import UIKit
class Signup2ViewController: UIViewController {
#IBOutlet weak var Email: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
Email.leftViewMode = .always
let imageview = UIImageView()
imageview.frame = CGRect(x: 0, y: 0, width: 5.0, height: 5.0)
view.addSubview(imageview)
let icon = UIImage(named: "c.png")
imageview.image = icon
Email.leftView = imageview
// Do any additional setup after loading the view.
}
}
To set the frame for your imageView you need to subclass UITextField and override leftViewRect(forBounds:). The code below will result in a 20x20 view offset 10 points from the left and centered vertically.
class AwesomeTextField: UITextField {
override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
let leftViewHeight: CGFloat = 20
let y = bounds.size.height / 2 - leftViewHeight / 2
return .init(x: 10, y: y, width: leftViewHeight, height: leftViewHeight)
}
}
To add an imageView to the textField you would do this:
class ViewController: UIViewController {
#IBOutlet weak var textField: AwesomeTextField!
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView()
imageView.image = UIImage(named: "c")
textField.leftView = imageView
textField.leftViewMode = .always
}
}
Make sure you set the appropriate class name for the textField in the identity inspector of your storyboard.

How can I update a UIView width with a UISlider?

I'm trying to change the width of a UIView with a slider. My problem is that instead of updating the views width my code is adding new views. I don't know how to update the view with swift playgrounds.
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
var feelings01Slider: UISlider!
var feelingsWidth01 = 100
var dayFeelings01: UIView!
var dayFeelings02: UIView!
var dayFeelings03: UIView!
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
feelings01Slider = UISlider()
feelings01Slider.frame = CGRect(x: 62, y: 375, width: 250, height: 20)
feelings01Slider.minimumValue = 1
feelings01Slider.maximumValue = 248
feelings01Slider.value = 100
feelings01Slider.isContinuous = true
feelings01Slider.addTarget(self, action: #selector(sliderValueDidChange(sender:)), for: .valueChanged)
setUpFeelings()
view.addSubview(feelings01Slider)
}
func setUpFeelings() {
feelingsWidth01 = Int(feelings01Slider.value)
var feelingsX02 = feelingsWidth01 + 62
var feelingsWidth02 = 80
var feelingsX03 = feelingsX02 + feelingsWidth02
var feelingsWidth03 = 70
dayFeelings01 = UIView(frame: CGRect(x: 62, y: 100, width: feelingsWidth01, height: 250))
dayFeelings01.backgroundColor = .yellow
dayFeelings02 = UIView(frame: CGRect(x: feelingsX02, y: 100, width: feelingsWidth02, height: 250))
dayFeelings02.backgroundColor = .blue
dayFeelings03 = UIView(frame: CGRect(x: feelingsX03, y: 100, width: feelingsWidth03, height: 250))
dayFeelings03.backgroundColor = .red
view.addSubview(dayFeelings01)
view.addSubview(dayFeelings02)
view.addSubview(dayFeelings03)
}
#objc func sliderValueDidChange(sender:UISlider) {
feelingsWidth01 = Int(sender.value)
dayFeelings03.removeFromSuperview()
dayFeelings02.removeFromSuperview()
dayFeelings01.removeFromSuperview()
setUpFeelings()
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
I'm new to programming so excuse me if my code seems messy.
You don't need to replace the views with new, differently-sized views . You can just change their frames. Replace your slider selector action with this:
#objc func sliderValueDidChange(sender:UISlider) {
dayFeelings01.frame.size.width = CGFloat(sender.value)
}
Note: because the yellow view was added first, it is expanding underneath the other views. That's why you can't see it get wider. Try changing the order so it's added last and you'll see it. If you want the other views to adjust to the available space, you can update their frames too, a UIStackView might make that easy.
Good luck!

Refresh View After Data Changes

Im trying to make real time chat, It is going good but I have a problem.
I have added a subview to navigationController instead of title. I have an avatar, full name of user and status in this view like whatsapp. I have got user is online string from pusher service and I want to display it in my subview bottom of user full name like whatsapp. How can I refresh the view when I get online string from func onPresenceChanged(stateChange method ?
I have added self.navbar.setNeedsDisplay() but it is not working.
ChatViewController.swift (I cropped it for quick review)
class ChatViewController: UIViewController, UITextFieldDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, PCRoomDelegate {
var navbarView = UIView()
var navbarAvatar = UIImageView()
var navbar = UILabel()
var statusString = [String]()
var usernameString = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.navbarView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width / 1.4, height: 44.0))
self.navbarView.backgroundColor = UIColor.clear
self.navbar = UILabel(frame: CGRect(x: 44.0, y: 0.0, width: UIScreen.main.bounds.width / 1.4 - 44, height: 44.0))
self.navbar.backgroundColor = UIColor.clear
self.navbar.numberOfLines = 2
self.navbar.textAlignment = NSTextAlignment.left
let bodyText = NSMutableAttributedString(string: "Halil İbrahim YÜCE", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16, weight: .bold)])
usernameString.append("\n#" + "halilyc")
bodyText.append(NSAttributedString(string: usernameString.last!, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : UIColor.gray]))
self.navbar.attributedText = bodyText
self.navbarView.addSubview(navbar)
self.navigationItem.titleView = self.navbarView
}
func onPresenceChanged(
stateChange: PCPresenceStateChange,
user: PCUser
) {
print("User \(user.displayName)'s presence changed to \(stateChange.current.rawValue)")
self.statusString.append(stateChange.current.rawValue)
self.navbar.setNeedsDisplay()
if statusString.count != 0 {
self.usernameString.append("\n#" + statusString.last!)
}
}
}
Assigning a string variable to a UILabel's attributedText property doesn't create a binding between that string and the label; you need to update attributedText if you want to see an updated value in your UI. Also, UI updates must be performed on the main thread; your update from the network will be delivered on a background thread.
Finally, I don't see any need to keep an array of statuses, you just need the most recent.
You can refactor to create a computed variable that provides the current user status text for your navigation bar.
It isn't clear how you are intending to display the display name, the username and the status (There are 3 things, but only 2 lines). I have just made it three lines and you can adapt as you require.
class ChatViewController: UIViewController, UITextFieldDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, PCRoomDelegate {
var navbarView: UIView!
var navbarAvatar: UIImageView!
var navbar: UILabel!
var status: String? {
didSet {
self.updateNavText()
}
var username: String? {
didSet {
self.updateNavText()
}
var displayName: String?
didSet {
self.updateNavText()
}
var statusText: NSAttributedString {
let text = NSMutableAttributedString(string: displayName ?? "", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16, weight: .bold)])
if let username = self.username {
text.append("\n#\(username)")
}
if let status = self.status {
text.append("\n\(status)")
}
return text
}
override func viewDidLoad() {
super.viewDidLoad()
self.navbarView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width / 1.4, height: 44.0))
self.navbarView.backgroundColor = UIColor.clear
self.navbar = UILabel(frame: CGRect(x: 44.0, y: 0.0, width: UIScreen.main.bounds.width / 1.4 - 44, height: 44.0))
self.navbar.backgroundColor = UIColor.clear
self.navbar.numberOfLines = 2
self.navbar.textAlignment = NSTextAlignment.left
let bodyText = NSMutableAttributedString(string: "Halil İbrahim YÜCE", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16, weight: .bold)])
self.updateNavText()
self.navbarView.addSubview(navbar)
self.navigationItem.titleView = self.navbarView
}
func onPresenceChanged(
stateChange: PCPresenceStateChange,
user: PCUser
) {
print("User \(user.displayName)'s presence changed to \(stateChange.current.rawValue)")
DispatchQueue.main.async {
self.status = stateChange.current.rawValue
}
}
func updateNavText() {
self.navbar.attributedText = self.statusText
}
You can manage things like:
First, create a function to set up your all UI objects adding on viewController's view or whatever you want to add. Call this method (like setupInitialLayout()) in viewDidLoad(). By calling this method in viewDidLoad(), because you just need to add components only once and you don't need to call this method again.
Now create another method in which write your all code like set your data whatever you want to display. Call this method (like setupData()) in viewWillAppear(). Also, you can call this method setupData() whenever you need like just user is online you are chatting with and you want to show as Online, just call this method only.

Making Image Slider with UIScrollView in Swift

I am making an app that the user can upload 1 to 3 photos.
I want the user to be able to see them it as a slider in with Page Control,
I started to code it but for some reason the images do not added to the scrollView (I see nothing when running the app).
This is my code so far:
class dogProfileViewController: UIViewController {
var imagesArray = [UIImageView()]
#IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let image1: UIImageView = UIImageView(image: UIImage(named: "image1.png"))
let image2: UIImageView = UIImageView(image: UIImage(named: "image2.png"))
imagesArray.append(image1)
imagesArray.append(image2)
var countIndex = CGFloat(0)
for image in imagesArray {
image.frame = CGRectMake(countIndex*view.frame.width, 0, view.frame.width, 100)
scrollView.addSubview(image)
countIndex = countIndex + 1
}
// Do any additional setup after loading the view.
}
}
Add the following line after the for loop ends
scrollView.contentSize = CGSizeMake(countIndex*view.frame.width,0)
I think this will work.
#IBOutlet var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 175)
imageArray = [#imageLiteral(resourceName: "cake"),#imageLiteral(resourceName: "food")]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
}
Well, according to what you provided, you haven't added the scrollView to the view. So, first step, make sure the scrollView is added to the view. self.view.addSubiew(scrollView). Change the scrollView background to make sure it is there.
Also, I don't see that you have initialized the scrollView frame. The scrollView has no frame, so it won't show anywhere. Make sure that you initialize the scrollView.

Resources