Calling a function (containing variable) in another class - ios

I have a relatively simple question. I created a function - covers the contents to retrieve data from the API. I need to call a function in several different classes (don't want to duplicate). I am calling that function, but nothing is getting displayed. If this function is a part of class where I want to call it, it works correctly. Where is the problem, please let me know. (I think in UIView...)? Thank you.
My function:
func loadScreen() {
var loadView:UIView!
loadView = UIView(frame: self.view.frame)
loadView!.backgroundColor = UIColor.black
loadView!.alpha = 1.0
let actView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
actView.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
actView.center = CGPoint(x: self.view.bounds.size.width / 2 , y: self.view.bounds.size.height / 2 )
actView.startAnimating()
loadView?.addSubview(actView)
self.view.addSubview(loadView!)
}
I call a function in another class in viewDidLoad (), but as I said, nothing is displayed.

First create a singleton class like this
Singleton class
import UIKit
import Foundation
class Singleton: NSObject
{
static let sharedInstance = Singleton()
override init()
{
super.init()
}
func placeBlockerView(target : UIViewController)
{
var loadView:UIView!
loadView = UIView(frame: target.view.frame)
loadView!.backgroundColor = UIColor.black
loadView!.alpha = 1.0
let actView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
actView.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
actView.center = CGPoint(x: target.view.bounds.size.width / 2 , y: target.view.bounds.size.height / 2 )
actView.startAnimating()
loadView?.addSubview(actView)
target.view.addSubview(loadView!)
}
}
After that use it from where ever you want as required
like this
Singleton.sharedInstance.placeBlockerView(target: self)
This above line will add that UIView you have created to your view controller's view.
Let me know if it don't work.

Instead of adding it in the above, it is always advised to return the UIView from that method and in your subclass of UIViewController do the following.
func viewDidLoad() {
let loadView = loadScreen()
self.view.addSubView()
}

Related

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!

How to load view swift more than one time?

I have one view (DataInputContainerView) and i load that view to DataController. This is my code for load DataInputContainerView to DataController
var heightInput: CGFloat = 50
lazy var inputContainerView: DataInputContainerView = {
let dataInputContainerView = DataInputContainerView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.heightInput))
dataInputContainerView.dataController = self
return dataInputContainerView
}()
That code was work. But i want to load again, for example
#IBAction func loadAgain(sender: AnyObject) {
self.heightInput += 15
// Put here to load that view again
}
I want make height view +15 and load again
So you want code that will create multiple instances of your DataInputContainerView class?
Don't use a lazy property. That creates a single instance the first time it's called, and the returns the same instance each time thereafter.
Instead, create a function that returns a DataInputContainerView:
func makeDataInputContainerView(height: height: CGFloat) ->
DataInputContainerView {
let rect = CGRect(x: 0, y: 0, width: self.view.frame.width,
height: height)
let dataInputContainerView = DataInputContainerView(frame: rect)
dataInputContainerView.dataController = self
return dataInputContainerView
}
And then call it:
var height = 50
for (_ in 1...5) {
var newDataInputContainerView = makeDataInputContainerView(height: height)
self.view.addSubview(newDataInputContainerView)
}

UIActivityIndicatorView dialog over view

In my app I'm using a custom UIActivityIndicator view (this) and it works great.
I have an UITableView and I want the indicator over the tableview on loading data. To solve the problem I have created an empty view with a background above all and when I need to start indicator's animation I simply hide tableview and show the empty view + the indicator.
The result is this:
I saw somewhere that I can use instead something like this:
How can I do?
Thanks in advance.
You could try adding a translucent Black view over the Table View and put the custom activity indicator code as a subview in the Black view.
let aBlackView = UIView(frame: CGRectMake(0, 0, self.view.bounds.width, self.view.bounds.height))
aBlackView.backgroundColor = UIColor.blackColor()
aBlackView.alpha = 0.75 // Change the alpha depending on how much transparency you require
let aMainWindow = UIApplication.sharedApplication().delegate!.window
aMainWindow!!.addSubview(aBlackView)
/* Enter you code for NVActivityIndicatorViewable here */
aBlackView.addSubview(/* NVActivityIndicatorViewable */)
Once you are done with your request, you can remove the Black view by calling this code:
aBlackView.removeFromSuperview()
I created a activity showing screen . I used in every where in my project.
//ProgressBarNotification.swift
import Foundation
import UIKit
class ProgressBarNotification {
internal static var strLabel = UILabel()
internal static var messageFrame = UIView()
internal static var activityIndicator = UIActivityIndicatorView()
internal static func progressBarDisplayer(msg:String,indicator:Bool ){
let view1 = UIApplication.sharedApplication().delegate?.window!!.rootViewController?.view
view1?.userInteractionEnabled = false
strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = msg
strLabel.textColor = UIColor.whiteColor()
messageFrame = UIView(frame: CGRect(x: view1!.frame.midX - 90, y: view1!.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.7)
if indicator {
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
}
messageFrame.addSubview(strLabel)
view1!.addSubview(messageFrame)
}
internal static func removeProgressBar() {
let view1 = UIApplication.sharedApplication().delegate?.window!!.rootViewController?.view
_ = view1?.subviews.filter({ (view) -> Bool in
if view == ProgressBarNotification.messageFrame {
view.removeFromSuperview()
}
return false
})
ProgressBarNotification.messageFrame.removeFromSuperview()
view1?.userInteractionEnabled = true
}
deinit{
}
}
Usage
//To start Loader
ProgressBarNotification.progressBarDisplayer("Loading", indicator: true)
//Stop
ProgressBarNotification.removeProgressBar()

Pull to Refresh plug-in : PullToBounce Wrapper UIScrollView

I am trying to use this plugin as refresh action : https://github.com/entotsu/PullToBounce
One, issue is I can't understand his explanation.
Explanation given on the github
tableView.frame = yourFrame --> tableView is equal to scrollView.frame in my situation
yourFrame --> I have no idea what it is. The main frame ? Another Frame I have to create ?
bodyView.addSubview(tableViewWrapper) --> bodyView ? Main Frame here ? or Another frame ?
Here is my code for the scrollView for now. Any help on how to implement this plugin using a scrollView made via the storyboard.
class ProfileViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
func makeMock() {
let headerView = UIView()
headerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 64)
headerView.backgroundColor = UIColor.lightBlue
self.view.addSubview(headerView)
let headerLine = UIView()
headerLine.frame = CGRect(x: 0, y: 0, width: 120, height: 8)
headerLine.layer.cornerRadius = headerLine.frame.height/2
headerLine.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.8)
headerLine.center = CGPoint(x: headerView.frame.center.x, y: 20 + 44/2)
headerView.addSubview(headerLine)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
let bodyView = UIView()
bodyView.frame = scrollView.frame
bodyView.frame.y += 20 + 44
self.view.addSubview(bodyView)
let tableViewWrapper = PullToBounceWrapper(scrollView: scrollView)
bodyView.addSubview(tableViewWrapper)
tableViewWrapper.didPullToRefresh = {
NSTimer.schedule(delay: 2) { timer in
tableViewWrapper.stopLoadingAnimation()
}
}
makeMock()
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
One thing, I notice is that there is a View on top of my scrollView that disable me to view it and scroll it. Help here needed please.
Regards,
Hary
Take a look at the Example of this library.
yourFrame is nothing but your tableview class. For example if your tableView Class is named SampleTableView, then it goes like
let tableView = SampleTableView(frame: self.view.frame, style: UITableViewStyle.Plain).
You have to use another class to set up your tableView.

iOS multiple CALayers being added but only one gets applied

I want to add a left/right border to my textfield. It is an IBOutlet. Also if I also add the function to style the textfield inside of the didEdit delegate callback it will update correctly.
Here is my code. Inside of ViewDidLoad.
let leftLayer = CALayer()
leftLayer.frame = CGRect(x: 0, y: 0, width: 1, height: (password.frame.size.height - 1))
leftLayer.backgroundColor = UIColor.gray.cgColor
let rightLayer = CALayer()
rightLayer.frame = CGRect(x: password.frame.size.width - 1, y: 0, width: 1, height: (password.frame.size.height - 1))
rightLayer.backgroundColor = UIColor.gray.cgColor
password.layer.setNeedsDisplay()
password.layer.addSublayer(leftLayer)
password.layer.display()
password.layer.setNeedsDisplay()
password.layer.addSublayer(rightLayer)
password.layer.display()
I've taken out all code except
let rightLayer = CALayer()
rightLayer.frame = CGRect(x: password.frame.size.width - 1, y: 0, width: 1, height: (password.frame.size.height - 1))
rightLayer.backgroundColor = UIColor.gray.cgColor
password.layer.setNeedsDisplay()
password.layer.addSublayer(rightLayer)
password.layer.display()
But iOS simply will not add this layer. I tried the snippet below
var once = true
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if once {
styleTextViews()
once = false
}
}
The only thing that does work is if I call it from
func textFieldDidBeginEditing(_ textField: UITextField) {
styleTextViews()
}
Then it adds it just fine..
Your problem is in ViewDidLoad you need to set this code inside viewDidLayoutSubviews because it contains the correct frame
var once = true // as the function runs multiple times
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if once {
// here
once = false
}
}

Resources