Custom View in xib not working - ios

I have VPMOTPView custom view in my `.xib' like this.
class VerifyOTP: UIView {
#IBOutlet weak var otpView: VPMOTPView!
var emailID = ""
var userID = ""
#IBAction func resendOTPAction(_ sender: UIButton) {
print("asdds")
}
override func awakeFromNib() {
super.awakeFromNib()
otpView.otpFieldsCount = 4
otpView.otpFieldDefaultBorderColor = UIColor.blue
otpView.otpFieldEnteredBorderColor = UIColor.red
otpView.otpFieldBorderWidth = 2
otpView.delegate = self
// Create the UI
otpView.initalizeUI()
}
}
extension VerifyOTP: VPMOTPViewDelegate {
func hasEnteredAllOTP(hasEntered: Bool) {
print("Has entered all OTP? \(hasEntered)")
}
func enteredOTP(otpString: String) {
print("OTPString: \(otpString)")
}
}
Then in my 'ViewController'
var verifyOTPView: VerifyOTP?
self.verifyOTPView = VerifyOTP.fromNib()
self.verifyOTPView?.frame = CGRect(x: 20, y: 0, width: screenSize.width - 40, height: screenSize.height / 3)
self.view.addSubview(self.verifyOTPView!)
But by this I can see my RESEND OTP button on screen but OTPVIEW is not displayed.

From the screenshot it doesn't look like you have any constraints set up for your views?
If not try adding constraints and see if that fixes the problem.

Related

Swift 4 start with custom ViewController

I have chatting app. I decide to create SlideShow tutorial for it. Now I have problem. How can I run TutorialVC just once when user install the app?
Usually app starts with AuthVC. Now I want to run tutorialVC just once, and then when user close app and run it again, from auth like usually.
My tutorial VC:
class TutorialViewController: UIViewController, UIScrollViewDelegate {
#IBAction func understandButtonAction(_ sender: Any) {
}
#IBOutlet weak var understandButton: UIButton!
#IBOutlet weak var tutorialPageControl: UIPageControl!
#IBOutlet weak var tutorialScrollView: UIScrollView!
var images: [String] = ["1","2","3","4"]
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
override func viewDidLoad() {
super.viewDidLoad()
setup()
addSlider()
setupButton()
}
//===============================
//EVTAuthorizationViewController
//===============================
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.keyWindow?.windowLevel = UIWindowLevelStatusBar
}
override func viewWillDisappear(_ animated: Bool) {
UIApplication.shared.keyWindow?.windowLevel = UIWindowLevelNormal
}
//AddButton
func setupButton(){
understandButton.layer.cornerRadius = 20
}
#IBAction func buttonAction(_ sender: Any?) {
print("Successful")
}
//ScrollBars
func setup(){
self.understandButton.isHidden = true
tutorialScrollView.showsHorizontalScrollIndicator = false
tutorialScrollView.showsVerticalScrollIndicator = false
}
//ScrollView method
//=============================
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
tutorialPageControl.currentPage = Int(pageNumber)
if tutorialPageControl.currentPage == 3{
self.understandButton.isHidden = false
}else{
self.understandButton.isHidden = true
}
}
//Addslider with photo
func addSlider(){
tutorialPageControl.numberOfPages = images.count
for index in 0..<images.count{
let xPos = self.view.frame.size.width * CGFloat(index)
frame.origin.x = tutorialScrollView.frame.size.width * CGFloat(index)
//frame.size = view.frame.size
let imageView = UIImageView(frame: CGRect(x: xPos, y: 0, width: self.view.frame.width, height: self.view.frame.size.height))
imageView.image = UIImage(named: images[index])
imageView.contentMode = .scaleAspectFill
self.tutorialScrollView.addSubview(imageView)
}
tutorialScrollView.contentSize = CGSize(width: (view.frame.size.width * CGFloat(images.count)), height: view.frame.size.height)
tutorialScrollView.delegate = self
}
}
Use userDefaults. I suppose the understandButton is the button the user hits to skip the tutorial, so when when it's tapped set a true bool value for a key that you are going to use, here I've chosen "tutorial presented":
#IBAction func understandButtonAction(_ sender: Any) {
UserDefaults.standard.set(true, forKey: "tutorial presented")
}
and when the app launches, in the AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let window = (UIApplication.shared.delegate as! AppDelegate).window
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
if UserDefaults.standard.bool(forKey: "tutorial presented") == true {
let controller = storyboard.instantiateViewController(withIdentifier: "Your Navigation controller name")
window?.rootViewController = tutorialViewController()
} else {
let tutorial = storyboard.instantiateViewController(withIdentifier: "Your tutorial controller name")
window?.rootViewController = tutorial
}
window?.makeKeyAndVisible()
return true
}
You can use a flag and store it via NSUserDefaults.
extension UserDefaults {
private static let didLaunchAppOnceKey = "didLaunchAppOnce"
var didLaunchAppOnce: Bool {
get { return bool(forKey: UserDefaults.didLaunchAppOnceKey) }
set { set(newValue, forKey: UserDefaults.didLaunchAppOnceKey) }
}
}
Then before presenting your view controller, check if the flag is set:
if !UserDefaults.standard.didLaunchAppOnce {
// Set the flag to true, so on next launch, we won't enter in the if again
UserDefaults.standard.didLaunchAppOnce = true
// Present your VC
…
}

How to convert an ImageView to a PDF file

I have two of the StoryBoards containing TextFields and two Buttons.
The second StoryBoard has an ImageView received from the first StoryBoard.
I want to make the text in the TextField on the ImageView in the second StoryBoard and then convert it to a PDF file.
I found this code on the site and tried to use it, but I really did not know how to use it and I could not do that. Can someone help me?
import UIKit
import PDFKit
class ViewController: UIViewController {
#IBOutlet weak var textview: UITextField!
#IBOutlet weak var imageview1: UIImageView!
let PdfView = pdfViewController()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Button To send Data To Another view
#IBAction func aa(_ sender: Any)
{
let label = UILabel(frame: CGRect(x: 20, y: 20, width: 80, height: 30))
label.text = "Hello ...!"
label.font = UIFont.systemFont(ofSize: 20)
label.textColor = .black
view.addSubview(label)
sample1(label: label)
//sample2(label: label)
//sample3(label: label)
//sample4(label: label)
PdfView.imageview.clipsToBounds = true
view.addSubview(PdfView.imageview)
}
func sample1(label: UILabel) {
PdfView.imageview.contentMode = .scaleAspectFit
PdfView.imageview.image = UIImage(named: "AR1-1")?.with(view: label) { (parentSize, viewToAdd) in
print("parentSize: \(parentSize)")
viewToAdd.font = UIFont.systemFont(ofSize: 40)
viewToAdd.textColor = .yellow
viewToAdd.bounds = CGRect(x: 40, y: 40, width: 200, height: 40)
}
}
// Button To Move To Another View
#IBAction func ww(_ sender: Any)
{
}
}
extension UIView {
func copyObject<T: UIView> () -> T? {
let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? T
}
}
extension UIImage {
typealias EditSubviewClosure<T: UIView> = (_ parentSize: CGSize, _ viewToAdd: T)->()
func with<T: UIView>(view: T, editSubviewClosure: EditSubviewClosure<T>) -> UIImage {
if let copiedView = view.copyObject() as? T {
UIGraphicsBeginImageContext(size)
let basicSize = CGRect(origin: .zero, size: size)
draw(in: basicSize)
editSubviewClosure(size, copiedView)
copiedView.draw(basicSize)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
return self
}
}
extension UIImageView {
enum ImageAddingMode {
case changeOriginalImage
case addSubview
case addCopiedSubview
}
func drawOnCurrentImage<T: UIView>(view: T, mode: ImageAddingMode, editSubviewClosure: #escaping UIImage.EditSubviewClosure<T>) {
guard let image = image else {
return
}
let addSubView: (T) -> () = { view in
editSubviewClosure(self.frame.size, view)
self.addSubview(view)
}
switch mode {
case .changeOriginalImage:
self.image = image.with(view: view, editSubviewClosure: editSubviewClosure)
case .addSubview:
addSubView(view)
case .addCopiedSubview:
if let copiedView = view.copyObject() as? T {
addSubView(copiedView)
}
}
}
}
/
import UIKit
import PDFKit
class pdfViewController: UIViewController {
#IBOutlet weak var imageview: UIImageView!
let me = ViewController()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func sendbutton(_ sender: Any)
{
}
}

Label text not updating after scroll event

I'm trying to update text of a label after a scroll event. I have a print command that prints the correct value but the label is not updating.
Here's my code
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)") // this prints correct value
self.signalLabel.text = signalText[Int(x/w)] // this does not update
}
what's the deal?
Here's the complete view controller code. This view is called from a button click on the initial view controller. This view contains a UIScrollView and UIPageControl. The UIScrollView contains two images that can be scrolled back and forth. I want to update the label text based on image that is shown.
import UIKit
class SignalOneViewController: UIViewController, UIScrollViewDelegate {
// MARK: Properties
#IBOutlet weak var signalScrollView: UIScrollView!
#IBOutlet weak var signalPageControl: UIPageControl!
#IBOutlet weak var signalLabel: UILabel!
// MARK: - Button Actions
#IBAction func signalOneButton(_ sender: Any) {
print("signal one button clicked")
performSegue(withIdentifier: "SignalOneSegue", sender: self)
}
#IBAction func onCancelButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
let signalImages = ["signal1a.png", "signal1b.png"]
let signalText = ["Ready for play", "Untimed down"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidLayoutSubviews() {
self.loadScrollView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadScrollView() {
let pageCount : CGFloat = CGFloat(signalImages.count)
signalLabel.text = signalText[0]
signalScrollView.backgroundColor = UIColor.clear
signalScrollView.delegate = self
signalScrollView.isPagingEnabled = true
signalScrollView.contentSize = CGSize(width: signalScrollView.frame.size.width * pageCount, height: signalScrollView.frame.size.height)
signalScrollView.showsHorizontalScrollIndicator = false
signalScrollView.showsVerticalScrollIndicator = false
signalPageControl.numberOfPages = Int(pageCount)
signalPageControl.pageIndicatorTintColor = UIColor.lightGray
signalPageControl.currentPageIndicatorTintColor = UIColor.blue
signalPageControl.addTarget(self, action: #selector(self.pageChanged), for: .valueChanged)
for i in 0..<Int(pageCount) {
print(self.signalScrollView.frame.size.width)
let image = UIImageView(frame: CGRect(x: self.signalScrollView.frame.size.width * CGFloat(i), y: 0, width: self.signalScrollView.frame.size.width, height: self.signalScrollView.frame.size.height))
image.image = UIImage(named: signalImages[i])!
image.contentMode = UIViewContentMode.scaleAspectFit
self.signalScrollView.addSubview(image)
}
}
//MARK: UIScrollView Delegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let viewWidth: CGFloat = scrollView.frame.size.width
// content offset - tells by how much the scroll view has scrolled.
let pageNumber = floor((scrollView.contentOffset.x - viewWidth / 50) / viewWidth) + 1
signalPageControl.currentPage = Int(pageNumber)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)")
self.signalLabel.text = signalText[p]
print(">>> \(signalText[Int(x/w)])")
}
//MARK: page tag action
#objc func pageChanged() {
let pageNumber = signalPageControl.currentPage
var frame = signalScrollView.frame
frame.origin.x = frame.size.width * CGFloat(pageNumber)
frame.origin.y = 0
signalScrollView.scrollRectToVisible(frame, animated: true)
}
}
Make sure signalLabe IBOutlet is attached to your label in storyboard or xib

UIView disappears after user interaction

whenever I click a textfield inside the view, then click the other text field, the view disappears. Strange... Can anyone help?
I animate the view using facebook pop. Here is my animation engine code:
import UIKit
import pop
class AnimationEngine {
class var offScreenRightPosition: CGPoint {
return CGPoint(x: UIScreen.main.bounds.width + 250,y: UIScreen.main.bounds.midY - 75)
}
class var offScreenLeftPosition: CGPoint{
return CGPoint(x: -UIScreen.main.bounds.width,y: UIScreen.main.bounds.midY - 75)
}
class var offScreenTopPosition: CGPoint{
return CGPoint(x: UIScreen.main.bounds.midX,y: -UIScreen.main.bounds.midY)
}
class var screenCenterPosition: CGPoint {
return CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY - 75)
}
let ANIM_DELAY : Int = 1
var originalConstants = [CGFloat]()
var constraints: [NSLayoutConstraint]!
init(constraints: [NSLayoutConstraint]) {
for con in constraints {
originalConstants.append(con.constant)
con.constant = AnimationEngine.offScreenRightPosition.x
}
self.constraints = constraints
}
func animateOnScreen(_ delay: Int) {
let time = DispatchTime.now() + Double(Int64(Double(delay) * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: time) {
var index = 0
repeat {
let moveAnim = POPSpringAnimation(propertyNamed: kPOPLayoutConstraintConstant)
moveAnim?.toValue = self.originalConstants[index]
moveAnim?.springBounciness = 8
moveAnim?.springSpeed = 8
if (index < 0) {
moveAnim?.dynamicsFriction += 10 + CGFloat(index)
}
let con = self.constraints[index]
con.pop_add(moveAnim, forKey: "moveOnScreen")
index += 1
} while (index < self.constraints.count)
}
}
class func animateToPosisition(_ view: UIView, position: CGPoint, completion: ((POPAnimation?, Bool) -> Void)!) {
let moveAnim = POPSpringAnimation(propertyNamed: kPOPLayerPosition)
moveAnim?.toValue = NSValue(cgPoint: position)
moveAnim?.springBounciness = 8
moveAnim?.springSpeed = 8
moveAnim?.completionBlock = completion
view.pop_add(moveAnim, forKey: "moveToPosition")
}
}
Then here is my viewcontroller code where the view is inside in:
import UIKit
import pop
class LoginVC: UIViewController, UITextFieldDelegate {
override var prefersStatusBarHidden: Bool {
return true
}
#IBOutlet weak var emailLoginVCViewConstraint: NSLayoutConstraint!
#IBOutlet weak var emailLoginVCView: MaterialView!
#IBOutlet weak var emailAddressTextField: TextFieldExtension!
#IBOutlet weak var passwordTextField: TextFieldExtension!
var animEngine : AnimationEngine!
override func viewDidAppear(_ animated: Bool) {
self.emailLoginVCView.isUserInteractionEnabled = true
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.bringSubview(toFront: emailAddressTextField)
self.animEngine = AnimationEngine(constraints: [emailLoginVCViewConstraint])
self.emailAddressTextField.delegate = self
self.passwordTextField.delegate = self
emailAddressTextField.allowsEditingTextAttributes = false
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if (textField === emailAddressTextField) {
passwordTextField.becomeFirstResponder()
} else if (textField === passwordTextField) {
passwordTextField.resignFirstResponder()
} else {
// etc
}
return true
}
#IBAction func emailTapped(_ sender: AnyObject) {
AnimationEngine.animateToPosisition(emailLoginVCView, position: AnimationEngine.screenCenterPosition, completion: { (POPAnimation, Bool)
in
})
}
#IBAction func exitTapped(_ sender: AnyObject) {
AnimationEngine.animateToPosisition(emailLoginVCView, position: AnimationEngine.offScreenRightPosition, completion: { (POPAnimation, Bool)
in
})
}
}
Last here is my hierchy and options: (my view's name is emailLoginVCView). Also when I was debugging when I clicked another textfield I set a breakpoint so I got this info: enter image description here
I have a constraint that binds the center of the login view with the center of the main screen
when I create the AnimationEngine,I pass it that constraint, and it sets its constant to be the offScreenRightPosition.x
when I bring up the email login sheet, I'm not changing the constant of the constraint; I'm just changing the position of the view
which means that autolayout thinks it’s supposed to still be offscreen
when the second textfield becomes active, that’s somehow triggering auto-layout to re-evaluate the constraints, and it sees that the login view’s position doesn’t match what the constraint says it should be so....
Autolayout moves it offscreen
So if I add this in emailTapped(_:), the problem goes away :)
#IBAction func emailTapped(_ sender: AnyObject) {
AnimationEngine.animateToPosisition(emailLoginVCView, position: AnimationEngine.screenCenterPosition, completion: { (POPAnimation, Bool)
in
self.emailLoginVCViewConstraint.constant = 0
})
}

UIButton not clickable when implemented from a class

I have a class ManageCell, which stores the frames, set the text of labels, etc... Which are the sub-views of an UIView CellView which is in the ViewController.
ManageCell:
import Foundation
import UIKit
class ManageCell {
var name: UILabel
var viewBelowButton: UIView
var deleteButton: UIButton
init (name: String) {
self.name = UILabel(frame: CGRectMake(10,15,250,40)
self.name.text = name
self.name.sizeToFit()
self.viewBelowButton = UIButton(frame: CGRectMake(UIScreen.mainScreen.bounds.width, 0, 70, 70)
//set outside the visible area so that it can be animated in.
self.viewBelowButton.backgroundColor = UIColor.redColor()
self.deleteButton = UIButton(frame: CGRectMake(0,0,70,70))
self.deleteButton.addTarget(ViewController.self, action: "deleteButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.deleteButton.setTitle("delete", forState: .Normal)
}
}
ViewController:
var cellView: [UIView] = []
var manageCells: [ManageCell] = []
...
//fill the manageCells array
func setSubViews () {
for (index, cell) in manageCells.enumerate() {
cellView.append(UIView(frame: CGRectMake(0, originY, view.bounds.width, 70)
cellView[index].addSubview(cell.name)
cellView[index].addSubview(cell.viewBelowButton)
cell.viewBelowButton.addSubview(cell.deleteButton)
}
}
func editing () {
var frame = CGRectMake(view.bound.width - 70, 0, 0, 70)
for cell in cells {
UIView.animateWithDuration(0.2, animations: {
cell.viewBelowButton.frame = frame
}
}
}
func deleteButtonPressed(sender: UIButton) {
print("button pressed")
}
User Interaction is enabled on both cellView[index], viewBelowButton and deleteButton.
The problem I'm facing is that the deleteButton does not respond to touches. The deleteButtonPressed: function is not being called.
code: https://github.com/an23lm/swift-stuff
I'm not sure if this is good practice, any suggestions are welcome.
Of course it's not called, ViewController.self is a class type, not your View Controller. And if even it was, it's not a good practice. You should use a delegate pattern here with some parameter to be returned back, so you will distinguish which cell delete button was pressed.
Example on your code:
protocol ManageCellDelegate: class {
func manageCellDeletePressed(id: Int)
}
class ManageCell {
var name: UILabel
var viewBelowButton: UIView
var deleteButton: UIButton
weak var delegate: ManageCellDelegate?
var id: Int
init (id: Int, name: String) {
self.id = id
self.name = UILabel(frame: CGRectMake(10,15,250,40))
self.name.text = name
self.name.sizeToFit()
self.viewBelowButton = UIButton(frame: CGRectMake(UIScreen.mainScreen().bounds.width, 0, 70, 70))
//set outside the visible area so that it can be animated in.
self.viewBelowButton.backgroundColor = UIColor.redColor()
self.deleteButton = UIButton(frame: CGRectMake(0,0,70,70))
self.deleteButton.addTarget(self, action: "deleteButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.deleteButton.setTitle("delete", forState: .Normal)
}
func deleteButtonPressed(sender: AnyObject) {
self.delegate?.manageCellDeletePressed(id)
}
}
class ViewController: UIViewController {
var cellView: [UIView] = []
var manageCells: [ManageCell] = []
func fullManageCells() {
for id in 0...15 {
let manageCell = ManageCell(id: id, name: "something")
manageCell.delegate = self
manageCells.append(manageCell)
}
}
}
extension ViewController: ManageCellDelegate {
func manageCellDeletePressed(id: Int) {
println("button with id \(id) pressed")
}
}

Resources