I have an issue.
I get an error below in the code saying: "Cannot convert value type 'Node' to expected argument type 'UIViewController' How to solve this?
the code for the document view controller is below:
import UIKit
import WebKit
import AEXML
import STPopup
import Kanna
import DropDownMenuKit
import Toaster
typealias DocumentOpenAction = (_ node: Node) -> ()
class DocumentViewController: BaseViewController {
var currentNode:Node! {
didSet {
if popupController == nil {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
if titleView != nil {
navigationItem.titleView = titleView
}
} else {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
}
}
}
//ausgegebene HTML's
var sections:[[String:String]] = []
var changeMarksVisible:Bool? {
didSet {
self.updateChangeMarking()
}
}
var nightModeOn:Bool? {
didSet {
self.updateNightMode()
}
}
var readAccessFolder:URL?
lazy var statusBarHeight: CGFloat = {
let statusBarSize = UIApplication.shared.statusBarFrame.size
return min(statusBarSize.width, statusBarSize.height)
}()
//
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(DocumentViewController.taskGotDeleted(withNotification:)), name: PackageManager.shared.tasksDeletedNotification, object: nil)
contentSizeInPopup = CGSize(width: 600, height: 500)
landscapeContentSizeInPopup = CGSize(width: 600, height: 500)
changeMarksVisible = UserDefaults.standard.bool(forKey: "ChangeMarkings")
nightModeOn = UserDefaults.standard.bool(forKey: "nightTheme")
if popupController == nil {
PackageManager.shared.setCurrentNodeAndAddToHistory(currentNode)
setupNavBar()
// create the drop down menu
createDropDownMenu()
//
jumpToGraphicsViewButton.addTarget(self, action: #selector(DocumentViewController.showGraphicsView), for: .touchUpInside)
jumpToGraphicsViewButtonLeadingConstraint.constant = 8.0
jumpToGraphicsViewButtonWidthConstraint.constant = 48.0
jumpToGraphicsViewButton.isEnabled = false
jumpToGraphicsViewButton.isHidden = false
} else {
setupNavBarForPreview()
//
jumpToGraphicsViewButton.isHidden = true
jumpToGraphicsViewButtonLeadingConstraint.constant = 0.0
jumpToGraphicsViewButtonWidthConstraint.constant = 0.0
}
// webview
setupWebview()
// process html of current node
splitHTML(forCurrentNode: currentNode)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
PackageManager.shared.currentDisplayedModuleNode = currentNode
navigationBarMenu?.container = view
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (ctx) in
self.show3dModelButtonLeadConstraint?.constant = self.view.frame.width - 50
self.show3dModelButton?.updateConstraintsIfNeeded()
self.webview?.scrollView.updateConstraintsIfNeeded()
// If we put this only in -viewDidLayoutSubviews, menu animation is
// messed up when selecting an item
self.updateMenuContentOffsets()
}) { (ctx) in
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
URLCache.shared.removeAllCachedResponses()
}
deinit {
NotificationCenter.default.removeObserver(self)
webview?.scrollView.delegate = nil
}
func showListOfContent(_ sender: AnyObject) {
_ = navigationController?.popViewController(animated: true)
}
}
// MARK: - UI
extension DocumentViewController {
func setupWebview() {
//Content Controller object
let controller = WKUserContentController()
//Add message handler reference
controller.add(self, name: "shoppingcart")
//Create configuration
let configuration = WKWebViewConfiguration()
configuration.userContentController = controller
var f = webViewView.frame
f.origin.y = 0
webview = WKWebView(frame: f, configuration: configuration)
webview?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webview?.backgroundColor = .white
webview?.scrollView.bounces = true
webview?.scrollView.delegate = self
webview?.navigationDelegate = self
webview?.uiDelegate = self
webViewView.addSubview(webview!)
webview?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func setupNavBar() {
//loads nav bar if not presented in popup
settingsButton = UIBarButtonItem(image: UIImage(named: "Settings"), style: .plain, target: self, action: #selector(DocumentViewController.showSettings(_:)))
navigationItem.rightBarButtonItems = [noticeButton,settingsButton]
listOfContentButton = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.showListOfContent(_:)))
shoppingCartButton = UIBarButtonItem(image: UIImage(named: "Checkout"), style: .plain, target: self, action: #selector(DocumentViewController.shoppingCartButtonPressed(_:)))
taskListButton = ZABarButtonItem(image: UIImage(named: "TaskList"), style: .plain, target: self, action: #selector(DocumentViewController.taskListButtonPressed(_:)))
taskListButton.isSelected = PackageManager.shared.nodeIsInTasks(currentNode)
taskListButton.tintColor = taskListButton.isSelected ? navigationController?.navigationBar.tintColor : .lightGray
favoritesButton = ZABarButtonItem(image: UIImage(named: "Star"), style: .plain, target: self, action: #selector(DocumentViewController.favoritesButtonPressed(_:)))
favoritesButton.isSelected = PackageManager.shared.nodeIsInFavorites(currentNode)
let img = favoritesButton.isSelected ? UIImage(named: "StarFilled"): UIImage(named: "Star")
favoritesButton.image = img
backToManualStructure = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.structureButtonPressed(_:)))
var items:[UIBarButtonItem] = [backToManualStructure,shoppingCartButton, favoritesButton]
if currentNode.canBeAddedToTasks() {
items.append(taskListButton)
}
navigationItem.leftBarButtonItems = items
}
func setupNavBarForPreview() {
//loads nav bar if presented in popup
closeButton = UIBarButtonItem(title: NSLocalizedString("Close", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.cancel))
navigationItem.leftBarButtonItems = [closeButton]
navigationItem.leftItemsSupplementBackButton = false
openButton = UIBarButtonItem(title: NSLocalizedString("Open in new tab", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.openDocument))
navigationItem.rightBarButtonItems = [openButton]
}
}
// MARK: - DropDownMenu
extension DocumentViewController {
func createDropDownMenu() {
// create the drop down menu
let title = prepareNavigationBarMenuTitleView()
prepareNavigationBarMenu(title)
updateMenuContentOffsets()
}
func prepareNavigationBarMenuTitleView() -> String {
// Both title label and image view are fixed horizontally inside title
// view, UIKit is responsible to center title view in the navigation bar.
// We want to ensure the space between title and image remains constant,
// even when title view is moved to remain centered (but never resized).
titleView = DropDownTitleView(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
titleView.addTarget(self,
action: #selector(DocumentViewController.willToggleNavigationBarMenu(_:)),
for: .touchUpInside)
titleView.addTarget(self,
action: #selector(DocumentViewController.didToggleNavigationBarMenu(_:)),
for: .valueChanged)
titleView.titleLabel.textColor = UIColor.black
titleView.title = currentNode.title
navigationItem.titleView = titleView
return titleView.title!
}
func prepareNavigationBarMenu(_ currentChoice: String) {
navigationBarMenu = DropDownMenu(frame: view.bounds)
navigationBarMenu?.delegate = self
var cells:[DropDownMenuCell] = []
for (index, doc) in PackageManager.shared.openNodes.enumerated() {
let cell = DropDownMenuCell()
cell.textLabel!.text = doc.title
cell.tag = index
cell.menuAction = #selector(DocumentViewController.choose(_:))
cell.menuTarget = self
if currentChoice == doc.title {
cell.accessoryType = .checkmark
}
cells.append(cell)
}
navigationBarMenu?.menuCells = cells
// If we set the container to the controller view, the value must be set
// on the hidden content offset (not the visible one)
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
// For a simple gray overlay in background
navigationBarMenu?.backgroundView = UIView(frame: view.bounds)
navigationBarMenu?.backgroundView!.backgroundColor = UIColor.black
navigationBarMenu?.backgroundAlpha = 0.7
}
func updateMenuContentOffsets() {
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
}
#IBAction func choose(_ sender: AnyObject) {
let cell = (sender as! DropDownMenuCell)
titleView.title = cell.textLabel!.text
let index = cell.tag
let node = PackageManager.shared.openNodes[index]
if node != currentNode {
initalSegment = 0
currentNode = node
setupNavBar()
splitHTML(forCurrentNode: currentNode)
}
if let menu = navigationBarMenu {
didTapInDropDownMenuBackground(menu)
}
}
#IBAction func willToggleNavigationBarMenu(_ sender: DropDownTitleView) {
sender.isUp ? navigationBarMenu?.hide() : navigationBarMenu?.show()
}
#IBAction func didToggleNavigationBarMenu(_ sender: DropDownTitleView) {
}
}
// MARK: - DropDownMenuDelegate
extension DocumentViewController : DropDownMenuDelegate {
func didTapInDropDownMenuBackground(_ menu: DropDownMenu) {
if menu == navigationBarMenu {
titleView.toggleMenu()
}
else {
menu.hide()
}
}
}
// MARK: - data module
extension DocumentViewController {
func splitHTML(forCurrentNode node:Node) {
node.deleteTemporaryHtmls()
if let nodePath = node.path {
let pathComponents = URL(fileURLWithPath: nodePath).pathComponents
if pathComponents.count >= 2 {
let rootFolder = "\(pathComponents[1])"
readAccessFolder = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(rootFolder)")
}
}
// segmented control
segmentedControl.removeAllSegments()
// process html of current node
do {
sections = try node.processHTMLSections()
if sections.count > 0 {
var index = 0
for sec in sections {
segmentedControl.insertSegment(withTitle: sec["title"], at: index, animated: false)
index += 1
}
//
let hasWCN = sections.first(where: { (sec) -> Bool in
return sec["contenttype"] == "safety"
})
if let _ = hasWCN {
} else {
let index = sections.index(where: { (sec) -> Bool in
return sec["contenttype"] == "container"
})
if let i = index {
initalSegment = i
}
}
//
if initalSegment > 5 {
initalSegment = 0
loadHTML(forSection: initalSegment)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
self.show3DModel(self.show3dModelButton as Any)
})
}
else {
if initalSegment > sections.count {
initalSegment = 0
}
loadHTML(forSection: initalSegment)
}
segmentedControl.selectedSegmentIndex = initalSegment
// configure show 3d model button
let button = UIButton(forAutoLayout: ())
button.imageView?.contentMode = .scaleAspectFit
button.imageView?.tintColor = .gray
button.setImage(UIImage(named: "Next"), for: .normal)
button.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
button.borderColor = .black
button.borderWidth = 1.0
button.addTarget(self, action: #selector(DocumentViewController.show3DModel(_:)), for: .touchUpInside)
webViewView.addSubview(button)
button.autoAlignAxis(.horizontal, toSameAxisOf: webViewView)
button.autoSetDimension(.height, toSize: 150.0)
button.autoSetDimension(.width, toSize: 50.0)
show3dModelButtonLeadConstraint = button.autoPinEdge(.trailing, to: .trailing, of: webViewView, withOffset: 0)
show3dModelButton = button
// we dont need the button any longer
show3dModelButton?.isHidden = true
}
} catch {
loadPDF()
segmentedControlHeight.constant = 0
segmentedControlMarginTop.constant = 0
segmentedControlMarginBottom.constant = 0
}
if let dmc = node.moduleCode {
dmcLabel.text = dmc
}
if let issno = node.issueNumber {
issnoLabel.text = issno
}
if let issdate = node.issueDate {
issdateLabel.text = DateFormatter.stringFromDate(issdate, format: "yyyy-MM-dd")
}
let edgePan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(returnToGraphicView))
edgePan.edges = .right
view.addGestureRecognizer(edgePan)
}
func loadHTML(forSection section: Int) {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if section > sections.count {
return
}
if webview?.isLoading == true {
webview?.stopLoading()
}
if let urlString = sections[section]["url"], let contenttype = sections[section]["contenttype"], let readAccessFolder = readAccessFolder {
var url = URL(fileURLWithPath: urlString)
if var components = URLComponents(url: url, resolvingAgainstBaseURL: false), contenttype == "requirements" {
let sc = URLQueryItem(name: "shoppingcart", value: "true")
let domain = URLQueryItem(name: "domain", value: "*")
components.queryItems = [sc, domain]
if let newUrl = components.url {
url = newUrl
}
}
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
}
}
func loadPDF() {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if webview?.isLoading == true {
webview?.stopLoading()
}
let fileStr = "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "")"
let url = URL(fileURLWithPath: fileStr)
let request = URLRequest(url: url)
if let readAccessFolder = readAccessFolder {
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
} else {
_ = webview?.load(request)
}
}
}
// MARK: - Illustrations
extension DocumentViewController {
func showFullscreenFigure(with boardNo: String, and components: URLComponents?) {
if let gv = self.storyboard?.instantiateViewController(withIdentifier: "GraphicsViewController") as? GraphicsViewController {
gv.url = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "").\(boardNo).$tmp.htm")
gv.caption = components?.queryItems?.filter({ (item) in item.name == "caption"}).first?.value
gv.javascript = components?.queryItems?.filter({ (item) in item.name == "javascript"}).first?.value
gv.readAccessFolder = readAccessFolder
graphicsView = gv
}
if popupController != nil {
popupController?.push(graphicsView!, animated: true)
} else {
navigationController?.pushViewController(graphicsView!, animated: true)
}
}
func showGraphicsView() {
if let graphicsView = graphicsView {
if popupController != nil {
popupController?.push(graphicsView, animated: true)
} else {
navigationController?.pushViewController(graphicsView, animated: true)
}
}
}
func returnToGraphicView(_ recognizer: UIScreenEdgePanGestureRecognizer) {
if recognizer.state == .recognized {
showGraphicsView()
}
}
}
// MARK: - Preview
extension DocumentViewController {
func cancel() {
onClose?()
}
func openDocument() {
onOpen?(currentNode)
}
func showPreview(for node:Node) {
let onOpen:DocumentOpenAction = { node in
self.currentNode = node
PackageManager.shared.setCurrentNodeAndAddToHistory(self.currentNode)
self.initalSegment = 0
self.splitHTML(forCurrentNode: self.currentNode)
self.createDropDownMenu()
}
let contentView = self.storyboard?.instantiateViewController(withIdentifier: "DocumentViewController") as! DocumentViewController
contentView.initalSegment = 0
contentView.currentNode = node
//
if popupController != nil {
contentView.onOpen = self.onOpen
contentView.onClose = self.onClose
self.popupController?.push(contentView, animated: true)
} else {
let popup = STPopupController(rootViewController: contentView)
popup.style = .formSheet
popup.hidesCloseButton = false
popup.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
popup.containerView.layer.cornerRadius = 4
contentView.onOpen = { node in
popup.dismiss(completion: {
onOpen(node)
})
}
contentView.onClose = {
popup.dismiss(completion: {
// we dont need to split the html again for now
// self.splitHTML(forCurrentNode: self.currentNode)
})
}
popup.present(in: self, completion: nil)
}
contentView.navigationItem.titleView = UILabel.forTitleView(withText: node.title)
}
func showProcedureStepCheckboxes() {
if popupController == nil {
self.webview?.evaluateJavaScript("showProcedureStepCheckboxes()", completionHandler: {(result, error) in
guard let err = error else {return}
print(err)
})
}
}
func setLastScrollingPosition() {
if let code = currentNode.contentobjectcode {
webview?.restoreContentOffset(forKey: code)
}
}
}
// MARK: - Settings
extension DocumentViewController {
func showSettings(_ sender: AnyObject) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SetSettingsViewController") as! SetSettingsViewController
vc.modalPresentationStyle = .popover
vc.onChange = {
self.changeMarksVisible = (UserDefaults.standard.bool(forKey: "ChangeMarkings"))
self.nightModeOn = (UserDefaults.standard.bool(forKey: "nightTheme"))
}
if let popover = vc.popoverPresentationController {
popover.barButtonItem = settingsButton
popover.permittedArrowDirections = .any
}
present(vc, animated: true, completion: nil)
}
func updateChangeMarking() {
if (self.changeMarksVisible ?? false) {
self.webview?.evaluateJavaScript("handleChangemarks()", completionHandler: {(result, error) in
})
}
else {
self.webview?.evaluateJavaScript("deleteChangemarks()", completionHandler: {(result, error) in
})
}
}
func updateNightMode() {
let mode = self.nightModeOn ?? false
self.webview?.evaluateJavaScript("s1000d.setNightMode(\(mode))", completionHandler: {(result, error) in
})
}
}
// Mark: - Structure Manual
extension DocumentViewController {
func structureButtonPressed(_ sender: AnyObject) {
PackageManager.shared.structureButtonPressed(currentNode)
if let root = self.parent?.parent as? RootTabBarViewController {
root.selectedIndex = 0
if let navController = root.viewControllers?.first as? UINavigationController, let firstController = navController.viewControllers.first as? ManualsViewController {
PackageManager.shared.strucutreArrayNode.removeLast()
for var i in PackageManager.shared.strucutreArrayNode {
print("\(i.title)")
// get next child node
if let next = i.nextChild() {
i = next
}
if i.type == "document" || i.subnodes.count == 0 {
firstController.showDocumentViewController(for: i)
} else {
firstController.navigationController?.pushViewController(i, animated: false)
}
}
}
}
}
}
Related
I have a Tab bar Controller to manage all the views. The problem I'm having is when I call a function in searchViewController (doAThing()) from HomeViewController which reloads the tableView in searchViewController, the tableView is empty when the Tab bar controller switches views.
Why does calling the doAThing method in my searchViewController not refresh my tableView?
How can I fill my tableView with values.
HomeViewController.swift
import UIKit
class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UISearchBarDelegate{
#IBOutlet weak var productCollectionView: UICollectionView!
#IBOutlet weak var storesCollectionView: UICollectionView!
#IBOutlet var searchQ: UISearchBar!
#IBOutlet weak var scrollView: UIScrollView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if(collectionView == storesCollectionView) {
return storesImages.count
}
return productsImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(collectionView == storesCollectionView) {
let cell2 = storesCollectionView.dequeueReusableCell(withReuseIdentifier: "storesCell", for: indexPath) as! StoreCollectionViewCell
cell2.compstoreImage.image = UIImage(named: storesImages[indexPath.row])
return cell2
}
else{
let cell = productCollectionView.dequeueReusableCell(withReuseIdentifier: "productsCell", for: indexPath) as! ProductCollectionViewCell
cell.pillImage.image = UIImage(named: productsImages[indexPath.row])
return cell
}
}
var productsImages:[String] = ["pcPic", "picturePC"]
var storesImages:[String] = ["newarkStore", "compeStore"]
override func viewDidLoad() {
super.viewDidLoad()
searchQ.delegate = self
scrollView.contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)
// searchQ.delegate = self
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//self.tabBarController?.tabBar.isHidden = false
}
func searchBarSearchButtonClicked(_ searchQ: UISearchBar)
{
print("*********")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "SearchViewController") as! searchViewController
// resultViewController.searchQuery = searchQ
resultViewController.doAthing(searchQ)
self.tabBarController?.selectedIndex = 3
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
resultViewController.resultsView.reloadData()
}
// func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
//
// print("*********")
//
// let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SearchViewController") as! searchViewController
// secondViewController.doAthing(searchBar)
// self.navigationController!.pushViewController(secondViewController, animated: true)
//
//
//
// //let titles: Elements = try doc.select("a[product-thumb]")
// //let titles: String = try doc.select("a").attr("product-thumb")
//
// // print(titles
//
// hideKeyboardWhenTappedAround()
//
// }
/*
// 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.destination.
// Pass the selected object to the new view controller.
}
*/
}
searchViewController.swift
import UIKit
import SwiftSoup
class searchViewController: UIViewController{
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var resultsView: UITableView!
#IBOutlet var searchQuery: UISearchBar!
// let content = try! String(contentsOf: URL(string: "https://www.locally.com/search/all/activities/depts?q=bottle")!)
// let doc: Document = try! SwiftSoup.parse(content)
var products: [String] = []
//let products = ["Computer", "PC", "Laptop"]
let stores = ["Computer Central", "Fry's Electronics", "Best Buy"]
//var stores: [String] = []
let into = ["Custom PC with high performanc. Perfect for gaming and streaming. Great condition", "Custom PC with high performanc. Perfect for gaming and streaming. Great condition", "Custom PC with high performanc. Perfect for gaming and streaming. Great condition"]
var dollars: [String] = []
//let dollars = [100, 220, 129, 100, 220, 129]
let likes = [10, 24, 24, 24 , 456, 46, 46]
//let miles = ["3.2 mi", "4.1 mi", "6.3 mi", "3.2 mi", "4.1 mi", "6.3 mi"]
var miles: [String] = []
// let names = ["Central Computers", "CompE", "geekStore", "Central Computers", "CompE", "geekStore"]
var names: [String] = []
let numbers = ["510-329-0172", "510-456-7345", "510-329-0172", "510-329-0172", "510-456-7345", "510-329-0172"]
var images: [UIImage] = []
var categories: [String] = []
var descriptions: [String] = []
var stars: [String] = []
var ratings: [Double] = []
var ratingImage: [[UIImage]] = [[]]
var phones: [String] = []
var cities: [String] = []
//var webCounter:Int = 0
var x:Double = 0
var y:Int = 0
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
searchQuery.delegate = self
resultsView.delegate = self
resultsView.dataSource = self
//set the height of each row in tableview
self.resultsView.rowHeight = 200.0
// Do any additional setup after loading the view.
}
#objc func loadList(notification: NSNotification) {
//load data here
self.resultsView.reloadData()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
//searchBar.inputViewController?.dismissKeyboard()
searchBar.inputViewController?.dismiss(animated: true)
doAthing(searchBar)
self.searchQuery.endEditing(true)
self.resultsView.keyboardDismissMode = .onDrag
hideKeyboardWhenTappedAround()
}
func doAthing(_ searchBar: UISearchBar) {
do {
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.medium
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
print("reached here")
let html = try String(contentsOf: URL(string: "https://www.locally.com/search/all/activities/depts?q=" + searchBar.text!)!)
//let doc: Document = try SwiftSoup.parse(html)
guard let titles: Elements = try? SwiftSoup.parse(html).getElementsByClass("product-thumb ") else {return}//select("a") else {return}
guard let prices: Elements = try? SwiftSoup.parse(html).getElementsByClass("product-thumb-price dl-price") else {return}
guard let Stores: Elements = try? SwiftSoup.parse(html).getElementsByClass("filter-label-link") else {return}
guard let Images: Elements = try? SwiftSoup.parse(html).getElementsByClass("product-thumb-img") else {return}
products = []
miles = []
dollars = []
names = []
images = []
stars = []
for title: Element in titles.array() {
print("title" + String(titles.size()))
products.append(try! title.attr("data-product-name"))
guard let url: URL = try? URL(string: "https://www.locally.com/" + String(try! title.attr("href")))
else
{
miles.append("-")
continue
}
let html1 = try String(contentsOf: url)
guard let distances: Element = try? SwiftSoup.parse(html1).getElementsByClass("conv-section-distance dl-store-distance").first()
else
{
miles.append("-")
continue
}
print(try! distances.ownText())
miles.append(try! distances.ownText())
guard let K: Array<String> = try? SwiftSoup.parse(html1).getElementsByClass("breadcrumbs container").eachText() else {return}
let str = (try! K.last!.components(separatedBy: "/") )
categories.append(str[str.count - 2])
print(str[str.count - 2])
guard let desc: Array<String> = try? SwiftSoup.parse(html1).getElementsByClass("pdp-information").eachText() else {return}
guard let s:String = try? desc[1]
else {
return
}
descriptions.append( String( s.suffix(s.count - 19) ) )
print( String( s.suffix(s.count - 19) ) )
guard let star: Element = try? SwiftSoup.parse(html1).getElementsByClass("stars").first()
else
{
print("no reviews")
ratings.append(0)
continue
}
print(try! star.attr("data-rating"))
//ratings.append(try! star.attr("data-rating")) ?? ()
let x = Double(try! star.attr("data-rating")) ?? 0
print("y: " + String(Int(x)))
ratings.append(x)
guard let locations: Element = try? SwiftSoup.parse(html1).getElementsByClass("conv-section-store-address section-subtitle dl-store-address js-store-location").first()
else
{
print("cant find city")
return
}
let string = locations.ownText()
print("location: " + String(string.prefix(string.count - 10)) )
cities.append(try! String(string.prefix(string.count - 10)))
guard let phoneNums: Element = try? SwiftSoup.parse(html1).getElementsByClass("selected-retailer-info-link btn-action-sm tooltip").first()
else
{
print("link not found")
return
}
guard let urls:URL = try? URL(string: "https://www.locally.com/" + phoneNums.attr("href") )
else
{
return
}
let html2 = try String(contentsOf: urls )
guard let storePage:Element = try? SwiftSoup.parse(html2).getElementsByClass("landing-page-phone-label").first() else {
print("Phone Number not found")
return
}
let sp = try? storePage.ownText
if let s = sp {
phones.append(try! s())
}
else {
phones.append("N/A")
}
print(try! storePage.ownText())
//
// let html1 = try String(contentsOf: url)
}
for price: Element in prices.array() {
print("prices" + String(prices.size()))
print(String(try! price.ownText()))
dollars.append(try! price.ownText())
}
for store: Element in Stores.array() {
print("Stores" + String(Stores.size()))
names.append(try! store.ownText()) ?? names.append("N/A")
}
for image: Element in Images.array() {
guard let url = URL(string: try! image.attr("src") ) else { return }
let data = try? Data(contentsOf: url)
if let imageData = data {
images.append( UIImage(data: imageData)! )
}
else {
images.append(UIImage(named: "pcPic")!)
}
//images.append(try! image.downloaded(from: image.attr("src")))
}
dismiss(animated: false, completion: nil)
resultsView.reloadData()
//let titles: Elements = try doc.select("a[product-thumb]")
//let titles: String = try doc.select("a").attr("product-thumb")
// print(titles)
} catch Exception.Error(type: let type, Message: let message) {
print(type)
print(message)
} catch {
print("")
}
}
// override func viewWillAppear(_ animated: Bool) {
// super.viewWillAppear(animated)
// self.tabBarController?.tabBar.isHidden = false
// }
//When user changes segment, tableview is reloaded
#IBAction func segmentChanged(_ sender: Any) {
resultsView.reloadData();
}
/*
// 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.destination.
// Pass the selected object to the new view controller.
}
*/
func imageWithImage(image: UIImage, scaledToSize newSize: CGSize) -> UIImage {
UIGraphicsBeginImageContext(newSize)
image.draw(in: CGRect(x: 0 ,y: 20 ,width: newSize.width ,height: newSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!.withRenderingMode(.alwaysOriginal)
}
}
extension searchViewController: UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("reached here")
switch segmentedControl.selectedSegmentIndex {
case 0:
return products.count
case 1:
return stores.count
case 2:
return (products.count + stores.count)
default:
break
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "resultsTableViewCell") as! resultsTableViewCell
switch segmentedControl.selectedSegmentIndex {
case 0:
cell.titleLabel?.text = products[indexPath.row]
cell.productImage?.image = images[indexPath.row]
// cell.descriptionLabel?.text = into[indexPath.row]
// cell.descriptionLabel?.numberOfLines = 0
cell.price?.text = String(dollars[indexPath.row])
cell.distance?.text = miles[indexPath.row]
cell.storeName?.numberOfLines = 0
cell.storeName?.text = names[indexPath.row]
cell.phoneNumber?.text = phones[indexPath.row]
let ratNumber = ratings[indexPath.row]
if( ratNumber == 0 )
{
cell.rating?.text = "No Reviews"
}
else
{
cell.rating?.text = String(ratNumber)
}
if(ratNumber > 4.5)
{
cell.star1.image = UIImage(named: "regular_5")
}
else if(ratNumber > 4.0)
{
cell.star1.image = UIImage(named: "regular_4_half")
}
else if(ratNumber == 4.0)
{
cell.star1.image = UIImage(named: "regular_4")
}
else if(ratNumber > 3.0)
{
cell.star1.image = UIImage(named: "regular_3_half")
}
else if(ratNumber == 3.0)
{
cell.star1.image = UIImage(named: "regular_3")
}
else if(ratNumber > 2.0)
{
cell.star1.image = UIImage(named: "regular_2_half")
}
else if(ratNumber == 2.0)
{
cell.star1.image = UIImage(named: "regular_2")
}
else if(ratNumber > 1.0)
{
cell.star1.image = UIImage(named: "regular_1_half")
}
else if(ratNumber == 1.0)
{
cell.star1.image = UIImage(named: "regular_1")
}
else
{
cell.star1.image = UIImage(named: "regular_0")
}
cell.rating?.numberOfLines = 0
// cell.phoneNumber?.text = numbers[indexPath.row]
case 1:
cell.titleLabel?.text = stores[indexPath.row]
cell.productImage?.image = imageWithImage(image: UIImage.init(named: "pcPic")!, scaledToSize: CGSize(width: 400, height: 300))
// cell.descriptionLabel?.text = into[indexPath.row]
// cell.descriptionLabel?.numberOfLines = 0
cell.price?.text = String(dollars[indexPath.row])
cell.distance?.text = miles[indexPath.row]
cell.storeName?.text = names[indexPath.row]
cell.phoneNumber?.text = numbers[indexPath.row]
case 2:
var all = products + stores
all.shuffle()
let alls = into + into
cell.titleLabel?.text = all[indexPath.row]
cell.productImage?.image = imageWithImage(image: UIImage.init(named: "pcPic")!, scaledToSize: CGSize(width: 400, height: 300))
// cell.descriptionLabel?.text = alls[indexPath.row]
// cell.descriptionLabel?.numberOfLines = 0
cell.price?.text = String(dollars[indexPath.row])
cell.distance?.text = miles[indexPath.row]
cell.storeName?.text = names[indexPath.row]
cell.phoneNumber?.text = numbers[indexPath.row]
default:
break
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// let vc = self.storyboard?.instantiateViewController(withIdentifier: "ShopViewController") as! ShopViewController
// self.present(vc, animated: true, completion: nil)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyboard.instantiateViewController(withIdentifier: "ProductViewController") as! ProductViewController
destinationVC.ktitle = products[indexPath.row]
destinationVC.kprice = dollars[indexPath.row]
// destinationVC.kdescription = [indexPath.row]
destinationVC.kimage = images[indexPath.row]
// destinationVC.klikes = likes[indexPath.row]
destinationVC.kcategory = categories[indexPath.row]
destinationVC.kdescription = descriptions[indexPath.row]
destinationVC.kname = names[indexPath.row]
destinationVC.kmiles = miles[indexPath.row]
destinationVC.klocation = cities[indexPath.row]
self.present(destinationVC, animated: true, completion: nil)
}
}
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard(_:)))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard(_ sender: UITapGestureRecognizer) {
view.endEditing(true)
if let nav = self.navigationController {
nav.view.endEditing(true)
}
}
}
First, it's probably not a good idea to switch to a different tab in that manner. Users understand that tapping a tab-bar icon/button takes them to a new tab. If you're jumping around in the tabs via code, it can be very confusing for the user.
But... it's your app.
The reason your code does not "refresh my tableView" is because you never actually reference that view controller.
In your code:
func searchBarSearchButtonClicked(_ searchQ: UISearchBar)
{
print("*********")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
// here you create a NEW instance of searchViewController
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "SearchViewController") as! searchViewController
// you call a func in that instance
resultViewController.doAthing(searchQ)
// you switch to tab index 3, which holds an OLD instance of searchViewController
self.tabBarController?.selectedIndex = 3
// you tell resultsView in the NEW instance to reloadData()
resultViewController.resultsView.reloadData()
// as soon as you exit this func, the NEW instance is deleted
}
You could do something like this:
func searchBarSearchButtonClicked(_ searchQ: UISearchBar)
print("*********")
// get a reference to the searchViewController that is already
// part of the tab bar controller
if let tb = self.tabBarController,
let controllers = tb.viewControllers,
let resultVC = controllers[3] as? searchViewController {
// call the func
resultVC.doAthing("new")
tb.selectedIndex = 3
}
}
However, that's really not a great approach... Just for one example, Suppose you change the order of the tabs at some point?
You're better off using either a custom tab bar controller class, or using a "data manager" class.
I'd suggest you head over to google (or your favorite search engine) and search for swift pass data between tab bar view controllers -- you'll find plenty of discussions, articles, examples, etc.
Edit -- comment
In HomeViewController replace your func searchBarSearchButtonClicked with this:
func searchBarSearchButtonClicked(_ searchQ: UISearchBar)
{
print("1 - searchBarSearchButtonClicked")
guard let btnTitle = searchQ.largeContentTitle else {
print("2 - FAILED to get searchQ.largeContentTitle")
return
}
print("2 - got btnTitle", btnTitle)
if let tb = self.tabBarController {
print("3 - got a tab bar controller reference")
if let controllers = tb.viewControllers {
print("4 - got controllers reference")
if controllers.count == 4 {
print("5 - we have 4 controllers")
if let resultVC = controllers[3] as? searchViewController {
print("6 - got a reference to searchViewController")
// if we have not yet selected the 4th tab,
// the view will not yet have been loaded
// so make sure it is
resultVC.loadViewIfNeeded()
// call the func, passing the button title
resultVC.doAthing(searchQ)
// switch to the 4th tab
tb.selectedIndex = 3
print("7 - we should now be at searchViewController")
} else {
print("6 - FAILED TO GET a reference to searchViewController")
}
} else {
print("5 - FAILED TO GET a reference to searchViewController")
}
} else {
print("4 - FAILED TO GET a reference to searchViewController")
}
} else {
print("3 - FAILED TO GET a reference to searchViewController")
}
}
Then see what messages get printed to the debug console.
I use MessageKit for create Chat in my App.
In ChatViewController which i created programmatically I added rightBarButtonItem with user picture. I want to add func which will be redirect on UserProfileViewController if other user hits on rightBarButtonItem.
Now it looks like this. User picture dedicated blue color with arrows.
Now I have this code:
class ChatsViewController: MessagesViewController {
override func viewDidLoad() {
super.viewDidLoad()
maintainPositionOnKeyboardFrameChanged = true
messageInputBar.sendButton.setImage(#imageLiteral(resourceName: "send"), for: .normal)
messageInputBar.sendButton.title = nil
messageInputBar.inputTextView.placeholder = NSLocalizedString("New message", comment: "Новое сообщение")
messageInputBar.delegate = self
messagesCollectionView.messagesDataSource = self
messagesCollectionView.messagesLayoutDelegate = self
messagesCollectionView.messagesDisplayDelegate = self
messagesCollectionView.messageCellDelegate = self
}
private func loadChat(channel: Channel) {
guard let id = channel.id else {
navigationController?.popViewController(animated: true)
return
}
reference = db.collection([FSCollections.chats, id, "thread"].joined(separator: "/"))
messageListener = reference?.addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error listening for channel updates: \(error?.localizedDescription ?? "No error")")
return
}
if UserDefaults.standard.bool(forKey: UserDefaultsKeys.switcherIsClick) == true {
self.navigationItem.title = self.channel?.recipientName ?? ""
} else {
self.navigationItem.title = self.channel?.name ?? ""
}
self.configurePhotoProfile()
snapshot.documentChanges.forEach { change in
self.handleDocumentChange(change)
}
}
}
func configurePhotoProfile() {
let imageView = UIImageView()
let widthConstraint = imageView.widthAnchor.constraint(equalToConstant: 34)
let heightConstraint = imageView.heightAnchor.constraint(equalToConstant: 34)
let tap = UITapGestureRecognizer(target: self, action: #selector(ChatsViewController.didTapImageButton(_:)))
tap.numberOfTouchesRequired = 1
heightConstraint.isActive = true
widthConstraint.isActive = true
imageView.kf.setImage(with: URL(string: channel?.recipientUrlImage ?? ""))
imageView.backgroundColor = .clear
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = 17
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tap)
if UserDefaults.standard.integer(forKey: UserDefaultsKeys.selectedSegmentedControl) == 0 {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: imageView)
} else {
self.navigationItem.rightBarButtonItem = nil
}
}
#objc func didTapImageButton(_ sender: UIBarButtonItem) {
if let detailPhotographerVC = storyboard?.instantiateViewController(withIdentifier: "detailPhotographerVC") as? DetailPhotographerViewController {
detailPhotographerVC.id = channel?.recipientID ?? ""
let backItem = UIBarButtonItem()
backItem.title = ""
self.navigationItem.backBarButtonItem = backItem
self.navigationController?.pushViewController(detailPhotographerVC, animated: true)
} else {
print("error")
}
}
}
So, if user tap on user picture I get an error in console from func didTapImageButton.
I don't understand why I get an error... On detailPhotographerVC I redirect correct id and detailPhotographerVC must not accept any data other than id.
UPD.
I try update my code in func didTapImageButton on:
#objc func didTapImageButton(_ sender: UIBarButtonItem) {
let detailPhotographerVC = storyboard!.instantiateViewController(withIdentifier: "detailPhotographerVC") as! DetailPhotographerViewController
detailPhotographerVC.id = channel?.recipientID ?? ""
let backItem = UIBarButtonItem()
backItem.title = ""
self.navigationItem.backBarButtonItem = backItem
self.navigationController?.pushViewController(detailPhotographerVC, animated: true)
}
But again get an error, check screenshot.
Load vc programmatically
let detailPhotographerVC = DetailPhotographerViewController()
from storyboard
let detailPhotographerVC = storyboard!.instantiateViewController(withIdentifier: "detailPhotographerVC") as! DetailPhotographerViewController
In my app, i have implemented card swipe feature using ZLSwipeable library. Now when i swipe right, means the answer is correct and swipe left then answer is incorrect. Lets suppose, i am having 5 cards then if i swipe 2 left and 3 right, then the corrected count should be 2 and incorrect count should be 3 which should be displayed on another screen named as Score VC which has 2 labels for corrected and incorrected count. When i swipe the last card, then it should navigate to Score VC, how do i implement it. the card first is flipped and then swiped or clicked. Means the flipped card also have two buttons on it , either you swipe left or click tick button, it does the same functionality and same goes for right swipe
My Flipcard VC code where the card swipe feature reside:
class FlipCardVC: UIViewController, UIGestureRecognizerDelegate, AVSpeechSynthesizerDelegate
{
#IBOutlet weak var exitTapPopup: UIView!
#IBOutlet weak var cardFlipPopup: UIView!
#IBOutlet weak var savePopup: UIView!
#IBOutlet var hideCardPopup: UIView!
#IBOutlet var audioAllowPopup: UIView!
#IBOutlet weak var switchState: UISwitch!
#IBOutlet weak var progressViewBar: UIProgressView!
#IBOutlet weak var cardOuterView: UIView!
var wordsData = [ModelResult]()
var cardId = Int()
var cardSoundIndex = 0
//MARK: ZLSwipeableView Properties
#IBOutlet weak var SwipeCardOuterView: UIView!
var swipeableView: ZLSwipeableView!
var colorIndex = 0
var cardIndex = 0
var loadCardsFromXib = false
let speechSynthesizer = AVSpeechSynthesizer()
var isCorrect: Bool = true
var correctAnswerArr = [String]()
var incorrectAnswerArr = [String]()
var cardView:CardView?
var trueCounter = 0
var falseCounter = 0
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
constrain(SwipeCardOuterView, view) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == view.bounds.width
view1.height == view.bounds.height
}
}
// MARK: CARD VIEW
func cardInit()
{
wordsData.shuffle()
swipeableView = ZLSwipeableView()
view.addSubview(swipeableView)
swipeableView.numberOfActiveView = 2
swipeableView.didStart = {view, location in
print("Did start swiping view at location: \(location)")
}
swipeableView.swiping = {view, location, translation in
print("Swiping at view location: \(location) translation: \(translation)")
}
swipeableView.didEnd = {view, location in
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
if self.swipeableView.direction == .Left
{
self.isCorrect = true
self.correctAnswerArr.append("\(self.isCorrect)")
print(self.correctAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempCorrectAnswer = "\(self.correctAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
else
{
self.isCorrect = false
self.incorrectAnswerArr.append("\(self.isCorrect)")
print(self.incorrectAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempincorrectAnswer = "\(self.incorrectAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
swipeableView.didSwipe = {view, direction, vector in
print("Did swipe view in direction: \(direction), vector: \(vector)")
if direction.description == "Right"
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_Favorite()
}
else
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_UNFavorite()
}
}
swipeableView.didCancel = {view in
print("Did cancel swiping view")
}
swipeableView.didTap = {view, location in
let cv = view as! CardView
if cv.contentview.tag == 0 {
cv.contentview.tag = 1
UIView.transition(with: view, duration: 0.7, options: .transitionFlipFromRight, animations: {
if self.wordsData.count > cv.tag
{
let data = self.wordsData[cv.tag] as ModelResult
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged != false
{
if let englishName = data.cardWordEnglish, englishName.count != 0
{
cv.contentview.wordLabel.text = englishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordEnglish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
self.speechSynthesizer.speak(speechUtterance)
}
else
{
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
cv.contentview.wordLabel.text = spanishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordSpanish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "es")
self.speechSynthesizer.speak(speechUtterance)
}
}
}, completion: { (complete) in
})
}
}
swipeableView.didDisappear = { view in
print("Did disappear swiping view")
}
constrain(swipeableView, view) { view1, view2 in
view1.left == view2.left+5
view1.right == view2.right-5
view1.top == view2.top + 50
view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
// view1.left == view2.left+50
// view1.right == view2.right-50
// view1.top == view2.top + 120
// view1.bottom == view2.bottom - 100
// view1.left == view2.left+16
// view1.right == view2.right-16
// view1.top == view2.top + 83 + (IS_IPHONE_X() ? 24 : 0)
// view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
}
self.loadCardsFromXib = true
self.colorIndex = 0
self.swipeableView.discardViews()
self.swipeableView.loadViews()
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if let swview = swipeableView
{
swview.nextView = {
return self.nextCardView()
}
}
}
#objc func yesBtnSwipeLeft(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Left)
trueCounter = trueCounter + 1
if colorIndex == self.wordsData.count{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(trueCounter, forKey: "trueCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func noBtnSwipeRight(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Right)
falseCounter = falseCounter + 1
print("THIS IS my counter: (falseCounter)")
if colorIndex == self.wordsData.count {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(falseCounter, forKey: "falseCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func soundBtn(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.audioAllowPopup)
}
#objc func hideCard(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.hideCardPopup)
}
func nextCardView() -> UIView?
{
let arrayData = wordsData
if (self.colorIndex >= arrayData.count)
{
return nil
}
self.cardView = CardView(frame: swipeableView.bounds)
if loadCardsFromXib
{
self.cardView!.contentview = Bundle.main.loadNibNamed("CardContentView", owner: self, options: nil)?.first! as? CardView
self.cardView!.contentview.superVC = self
self.cardView!.contentview.translatesAutoresizingMaskIntoConstraints = false
self.cardView!.contentview.backgroundColor = self.cardView!.backgroundColor
self.cardView!.addSubview(self.cardView!.contentview)
let data = arrayData[(self.colorIndex)] as ModelResult
self.cardView!.contentview.wordModel = data
self.cardView!.contentview.currentCardCountLbl.text = "\(self.colorIndex + 1)"+" "+"of"+" "+"\(wordsData.count)"
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged == false
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let englishName = data.cardWordEnglish, englishName.count != 0
{
self.cardView!.contentview.wordLabel.text = englishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
else
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
self.cardView!.contentview.wordLabel.text = spanishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
self.cardView!.contentview.soundBtn.addTarget(self, action:#selector(self.soundBtn(sender:)), for: .touchUpInside)
self.cardView!.contentview.hideCard.addTarget(self, action:#selector(self.hideCard(sender:)), for: .touchUpInside)
self.cardView!.contentview.soundBtn.tag = self.colorIndex
self.cardView!.contentview.hideCard.tag = self.colorIndex
self.cardView!.tag = self.colorIndex
constrain(self.cardView!.contentview, self.cardView!) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == self.cardView!.bounds.width
view1.height == self.cardView!.bounds.height
}
}
colorIndex += 1
return cardView
}
//MARK: API Parsing for deck words data
func WS_GetWords()
{
if ApiUtillity.sharedInstance.isReachable()
{
ApiUtillity.sharedInstance.StartProgress(view: self.view)
let url = "\(WS_GetWordsAPI)/\(cardId)"
APIClient<ModelBaseGetWordsData>().API_GET(Url: url, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
if(modelResponse.success == true)
{
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.colorIndex = 0
self.wordsData.removeAll()
if let array = modelResponse.result, array.count != 0
{
for data in array
{
self.wordsData.append(data)
}
self.cardInit()
}
else
{
self.colorIndex = 0
self.wordsData.removeAll()
DispatchQueue.main.asyncAfter(deadline: .now(), execute:
{
if self.swipeableView != nil
{
self.swipeableView.removeFromSuperview()
}
self.cardInit()
})
}
}
else
{
self.showToast(message: modelResponse.message!)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
if self.wordsData.count == 0
{
self.setNoDataMessage(message: modelResponse.message)
}
}) { (failed) in
self.showToast(message: failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
else
{
self.showToast(message: "No internet connection...")
}
}
my score vc code:
class ScoreVC: UIViewController {
#IBOutlet weak var progressScoreView: MBCircularProgressBarView!
#IBOutlet weak var correctAnswerLbl: UILabel!
#IBOutlet weak var incorrectAnswerLbl: UILabel!
var tempCorrectAnswer = String()
var tempincorrectAnswer = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.progressScoreView.value = 0.0
let correct = UserDefaults.standard.string(forKey: "trueCounter")
let incorrect = UserDefaults.standard.string(forKey: "falseCounter")
self.correctAnswerLbl.text = correct
self.incorrectAnswerLbl.text = incorrect
}
override func viewWillAppear(_ animated: Bool) {
self.setCounterToZero()
UIView.animate(withDuration: 10.0) {
self.progressScoreView.value = 50.0
}
}
func setCounterToZero(){
correctAnswerLbl.text = ""
incorrectAnswerLbl.text = ""
}
create 2 var variables to increase the value
var trueCounter = 0
var falseCounter = 0
Set a function in your ViewWillAppear for every time your screen reloads the counter do it aswell
override func viewWillAppear(_ animated: Bool) {
setCounterToZero()
}
func setCounterToZero(){
correctAnswerLbl.text = ""
incorrectAnswerLbl.text = ""
}
so in your swipe functions set the variables to increase
for false:
falseCounter = falseCounter + 1
for true
trueCounter = trueCounter + 1
when the game ends and sends the user to the ScoreVC
UserDefaults.standard.set(trueCounter, forKey: "trueCounter")
UserDefaults.standard.set(falseCounter, forKey: "falseCounter")
flipcardVC
class FlipCardVC: UIViewController, UIGestureRecognizerDelegate, AVSpeechSynthesizerDelegate
{
#IBOutlet weak var exitTapPopup: UIView!
#IBOutlet weak var cardFlipPopup: UIView!
#IBOutlet weak var savePopup: UIView!
#IBOutlet var hideCardPopup: UIView!
#IBOutlet var audioAllowPopup: UIView!
#IBOutlet weak var switchState: UISwitch!
#IBOutlet weak var progressViewBar: UIProgressView!
#IBOutlet weak var cardOuterView: UIView!
var wordsData = [ModelResult]()
var cardId = Int()
var cardSoundIndex = 0
//MARK: ZLSwipeableView Properties
#IBOutlet weak var SwipeCardOuterView: UIView!
var swipeableView: ZLSwipeableView!
var colorIndex = 0
var cardIndex = 0
var loadCardsFromXib = false
let speechSynthesizer = AVSpeechSynthesizer()
var isCorrect: Bool = true
var correctAnswerArr = [String]()
var incorrectAnswerArr = [String]()
var trueCounter = 0
var falseCounter = 0
var cardView:CardView?
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
constrain(SwipeCardOuterView, view) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == view.bounds.width
view1.height == view.bounds.height
}
}
// MARK: CARD VIEW
func cardInit()
{
wordsData.shuffle()
swipeableView = ZLSwipeableView()
view.addSubview(swipeableView)
swipeableView.numberOfActiveView = 2
swipeableView.didStart = {view, location in
print("Did start swiping view at location: \(location)")
}
swipeableView.swiping = {view, location, translation in
print("Swiping at view location: \(location) translation: \(translation)")
}
swipeableView.didEnd = {view, location in
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
if self.swipeableView.direction == .Left
{
self.isCorrect = true
self.correctAnswerArr.append("\(self.isCorrect)")
print(self.correctAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempCorrectAnswer = "\(self.correctAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
else
{
self.isCorrect = false
self.incorrectAnswerArr.append("\(self.isCorrect)")
print(self.incorrectAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempincorrectAnswer = "\(self.incorrectAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
swipeableView.didSwipe = {view, direction, vector in
print("Did swipe view in direction: \(direction), vector: \(vector)")
if direction.description == "Right"
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_Favorite()
}
else
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_UNFavorite()
}
}
swipeableView.didCancel = {view in
print("Did cancel swiping view")
}
swipeableView.didTap = {view, location in
let cv = view as! CardView
if cv.contentview.tag == 0 {
cv.contentview.tag = 1
UIView.transition(with: view, duration: 0.7, options: .transitionFlipFromRight, animations: {
if self.wordsData.count > cv.tag
{
let data = self.wordsData[cv.tag] as ModelResult
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged != false
{
if let englishName = data.cardWordEnglish, englishName.count != 0
{
cv.contentview.wordLabel.text = englishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordEnglish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
self.speechSynthesizer.speak(speechUtterance)
}
else
{
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
cv.contentview.wordLabel.text = spanishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordSpanish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "es")
self.speechSynthesizer.speak(speechUtterance)
}
}
}, completion: { (complete) in
})
}
}
swipeableView.didDisappear = { view in
print("Did disappear swiping view")
}
constrain(swipeableView, view) { view1, view2 in
view1.left == view2.left+5
view1.right == view2.right-5
view1.top == view2.top + 50
view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
// view1.left == view2.left+50
// view1.right == view2.right-50
// view1.top == view2.top + 120
// view1.bottom == view2.bottom - 100
// view1.left == view2.left+16
// view1.right == view2.right-16
// view1.top == view2.top + 83 + (IS_IPHONE_X() ? 24 : 0)
// view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
}
self.loadCardsFromXib = true
self.colorIndex = 0
self.swipeableView.discardViews()
self.swipeableView.loadViews()
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if let swview = swipeableView
{
swview.nextView = {
return self.nextCardView()
}
}
}
#objc func yesBtnSwipeLeft(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Left)
var finalTrue = 0
trueCounter = trueCounter + 1
print("THE USER SWIPE TO left")
print("///////////////////////////////////////////")
print(trueCounter)
print("///////////////////////////////////////////")
finalTrue = trueCounter
if colorIndex == self.wordsData.count{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(finalTrue, forKey: "trueCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func noBtnSwipeRight(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Right)
var finalFlase = 0
falseCounter = falseCounter + 1
print("THE USER SWIPE TO right")
print("///////////////////////////////////////////")
print(falseCounter)
print("///////////////////////////////////////////")
var finalFlase = falseCounter
print("THIS IS my counter: (falseCounter)")
if colorIndex == self.wordsData.count {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(finalFlase, forKey: "falseCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func soundBtn(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.audioAllowPopup)
}
#objc func hideCard(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.hideCardPopup)
}
func nextCardView() -> UIView?
{
let arrayData = wordsData
if (self.colorIndex >= arrayData.count)
{
return nil
}
self.cardView = CardView(frame: swipeableView.bounds)
if loadCardsFromXib
{
self.cardView!.contentview = Bundle.main.loadNibNamed("CardContentView", owner: self, options: nil)?.first! as? CardView
self.cardView!.contentview.superVC = self
self.cardView!.contentview.translatesAutoresizingMaskIntoConstraints = false
self.cardView!.contentview.backgroundColor = self.cardView!.backgroundColor
self.cardView!.addSubview(self.cardView!.contentview)
let data = arrayData[(self.colorIndex)] as ModelResult
self.cardView!.contentview.wordModel = data
self.cardView!.contentview.currentCardCountLbl.text = "\(self.colorIndex + 1)"+" "+"of"+" "+"\(wordsData.count)"
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged == false
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let englishName = data.cardWordEnglish, englishName.count != 0
{
self.cardView!.contentview.wordLabel.text = englishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
else
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
self.cardView!.contentview.wordLabel.text = spanishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
self.cardView!.contentview.soundBtn.addTarget(self, action:#selector(self.soundBtn(sender:)), for: .touchUpInside)
self.cardView!.contentview.hideCard.addTarget(self, action:#selector(self.hideCard(sender:)), for: .touchUpInside)
self.cardView!.contentview.soundBtn.tag = self.colorIndex
self.cardView!.contentview.hideCard.tag = self.colorIndex
self.cardView!.tag = self.colorIndex
constrain(self.cardView!.contentview, self.cardView!) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == self.cardView!.bounds.width
view1.height == self.cardView!.bounds.height
}
}
colorIndex += 1
return cardView
}
//MARK: API Parsing for deck words data
func WS_GetWords()
{
if ApiUtillity.sharedInstance.isReachable()
{
ApiUtillity.sharedInstance.StartProgress(view: self.view)
let url = "\(WS_GetWordsAPI)/\(cardId)"
APIClient<ModelBaseGetWordsData>().API_GET(Url: url, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
if(modelResponse.success == true)
{
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.colorIndex = 0
self.wordsData.removeAll()
if let array = modelResponse.result, array.count != 0
{
for data in array
{
self.wordsData.append(data)
}
self.cardInit()
}
else
{
self.colorIndex = 0
self.wordsData.removeAll()
DispatchQueue.main.asyncAfter(deadline: .now(), execute:
{
if self.swipeableView != nil
{
self.swipeableView.removeFromSuperview()
}
self.cardInit()
})
}
}
else
{
self.showToast(message: modelResponse.message!)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
if self.wordsData.count == 0
{
self.setNoDataMessage(message: modelResponse.message)
}
}) { (failed) in
self.showToast(message: failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
else
{
self.showToast(message: "No internet connection...")
}
}
and in your score labels score vc
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.progressScoreView.value = 0.0
let correct = UserDefaults.standard.string(forKey: "trueCounter")
let incorrect = UserDefaults.standard.string(forKey: "falseCounter")
self.correctAnswerLbl.text = correct
self.incorrectAnswerLbl.text = incorrect
}
override func viewWillAppear(_ animated: Bool) {
//don't add setCounterToZero()
UIView.animate(withDuration: 10.0) {
self.progressScoreView.value = 50.0
}
}
plz rate if was useful
I found some code to show PDF file and, the code has a pencil to draw on pdf but I want to change the pencil to text. When I click on button I can write a text and move the text anywhere on view
I want to add text and change the size and move it as I want.
//
// ViewController.swift
// PDFTest
//
// Created by Prashoor Chitnis on 22/11/17.
// Copyright © 2017 InfoBeans LLC. All rights reserved.
//
import UIKit
import PDFKit
struct PAIRAnn {
var drawing: PDFAnnotation;
var button: PDFAnnotation;
var currentPage: PDFPage;
}
class ViewController: UIViewController, PDFViewDelegate, DrawEventListener {
#IBOutlet weak var closeBtn: UIBarButtonItem!
#IBOutlet weak var saveBtn: UIBarButtonItem!
#IBOutlet weak var undoBtn: UIBarButtonItem!
#IBOutlet weak var pencil: UIBarButtonItem!
var selectedAnnotation = [PAIRAnn]()
var position: CGPoint?
var currentPage : PDFPage?
var pView: PDFView?
var pdfView : PDFView {
get {
if pView == nil {
pView = PDFView(frame: self.view.frame)
pView?.delegate = self
}
return pView!
}
}
var fadeView: UIView?
var messageView : UIView {
get {
if fadeView == nil {
fadeView = UIView(frame: CGRect(x: (self.view.frame.size.width - 300)/2, y: 30, width: 300, height: 55))
var frm = (fadeView?.bounds)!
frm.origin.y = 15
frm.size.height = 25
let text = UILabel(frame: frm)
text.textAlignment = .center
text.text = "Double-Click on any spot to begin"
text.font = UIFont.systemFont(ofSize: 16)
fadeView?.addSubview(text)
fadeView?.layer.cornerRadius = 27.5
fadeView?.layer.borderWidth = 1.5
fadeView?.backgroundColor = UIColor.white.withAlphaComponent(0.8)
}
return fadeView!
}
}
var drawVw: DrawScreen?
var drawView : DrawScreen {
get {
if drawVw == nil {
drawVw = DrawScreen(frame: self.view.frame)
drawVw?.listener = self
}
return drawVw!
}
}
private var gesture: UITapGestureRecognizer?
private var gestureRecognizer: UITapGestureRecognizer {
get {
if gesture == nil {
gesture = UITapGestureRecognizer.init(target: self, action: #selector(addDrawing(sender:)))
gesture?.numberOfTapsRequired = 2
}
return gesture!
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.closeBtn.isEnabled = false
self.saveBtn.isEnabled = false
self.undoBtn.isEnabled = false
self.pencil.isEnabled = true
self.view.insertSubview(self.pdfView, at: 0)
let url = Bundle.main.url(forResource: "EN8", withExtension: "pdf")
self.pdfView.document = PDFDocument.init(url: url!)
}
#IBAction func addPencil(_ sender: UIBarButtonItem) {
self.pencil.isEnabled = false
self.view.insertSubview(self.messageView, aboveSubview: self.pdfView)
self.pdfView.addGestureRecognizer(self.gestureRecognizer)
}
func removeMessage() {
if self.messageView.superview == nil {
return
}
UIView.animate(withDuration: 0.4, animations: {
self.messageView.transform = CGAffineTransform.init(translationX: 0, y: -70)
}) { (success) in
self.messageView.removeFromSuperview()
self.messageView.transform = CGAffineTransform.identity
}
}
#objc func addDrawing(sender: UITapGestureRecognizer) {
self.removeMessage()
self.position = sender.location(in: self.view)
self.view.insertSubview(self.drawView, at: 1)
currentPage = self.pdfView.currentPage
self.pdfView.go(to: currentPage!)
self.pencil.isEnabled = false
self.undoBtn.isEnabled = false
self.saveBtn.isEnabled = false
self.closeBtn.isEnabled = true
}
func pdfViewWillClick(onLink sender: PDFView, with url: URL) {
var checkVal = url.absoluteString
checkVal = checkVal.replacingOccurrences(of: "path://", with: "")
var draw: PDFAnnotation?
for ann in self.allLinks() {
let value = "\(ann.value(forAnnotationKey: PDFAnnotationKey(rawValue: "Link"))!)"
if checkVal == value {
draw = ann
break
}
}
var currpage: PDFPage? = nil
var button: PDFAnnotation?
for (btn, page) in self.allButtons() {
let value = "\(btn.value(forAnnotationKey: PDFAnnotationKey(rawValue: "_Path"))!)"
if checkVal == value {
currpage = page
button = btn
break
}
}
if draw != nil && button != nil && currpage != nil {
let color = draw?.value(forAnnotationKey: PDFAnnotationKey(rawValue: "_Color")) as! String
switch (color) {
case "red":
draw?.color = UIColor.red
break
default:
break
}
currpage?.removeAnnotation(button!)
self.editButtonItem.isEnabled = false
self.undoBtn.isEnabled = true
self.pencil.isEnabled = false
self.selectedAnnotation.append(PAIRAnn.init(drawing: draw!, button: button!, currentPage: currpage!))
}
}
#IBAction func undoAction(_ sender: Any) {
self.removeMessage()
if self.selectedAnnotation.count > 0 {
for pairs in self.selectedAnnotation {
pairs.drawing.color = UIColor.clear
pairs.currentPage.addAnnotation(pairs.button)
}
self.selectedAnnotation = []
self.closeBtn.isEnabled = false
self.saveBtn.isEnabled = false
self.undoBtn.isEnabled = false
self.pencil.isEnabled = true
}
else {
self.drawView.undo()
}
}
#IBAction func removeDrawing(sender: Any) {
self.removeMessage()
self.pdfView.removeGestureRecognizer(self.gestureRecognizer)
self.drawView.removeFromSuperview()
self.closeBtn.isEnabled = false
self.saveBtn.isEnabled = false
self.undoBtn.isEnabled = false
self.pencil.isEnabled = true
}
func drawDidBegin() {
self.undoBtn.isEnabled = true
self.saveBtn.isEnabled = true
}
func drawingGotEmpty() {
self.undoBtn.isEnabled = false
self.saveBtn.isEnabled = false
}
#IBAction func saveDrawing(_ sender: Any) {
self.pdfView.removeGestureRecognizer(self.gestureRecognizer)
self.currentPage = self.pdfView.page(for: self.drawView.touches[0].path.first!, nearest: true)
var arrayPath = [UIBezierPath]()
for touches in self.drawView.touches {
let bPth = UIBezierPath.init()
let point = self.pdfView.convert(touches.path.first!, to: self.currentPage!)
bPth.move(to: point)
if touches.path.count > 1 {
for i in 1...touches.path.count-1 {
let tch = self.pdfView.convert(touches.path[i], to: self.currentPage!)
bPth.addLine(to: tch)
}
}
arrayPath.append(bPth)
}
let ann = PDFAnnotation.init(bounds: (self.currentPage?.bounds(for: self.pdfView.displayBox))!, forType: PDFAnnotationSubtype.ink, withProperties: nil)
ann.shouldDisplay = false
for bPth in arrayPath {
ann.add(bPth)
}
ann.color = UIColor.clear
let stamp = "PAGE_\(Date.init().timeIntervalSince1970)"
ann.setValue(stamp, forAnnotationKey: PDFAnnotationKey.init(rawValue: "Link"))
ann.setValue("red", forAnnotationKey: PDFAnnotationKey.init(rawValue: "_Color"))
self.currentPage?.addAnnotation(ann)
let linkPoint = self.pdfView.convert(self.position!, to: self.currentPage!)
let linkAnn = PDFAnnotation.init(bounds: CGRect(x: linkPoint.x - 20, y: linkPoint.y - 12, width: 40, height: 24), forType: PDFAnnotationSubtype.widget, withProperties: nil)
linkAnn.widgetFieldType = .button
linkAnn.widgetDefaultStringValue = "Open"
linkAnn.widgetControlType = .pushButtonControl
linkAnn.action = PDFActionURL(url: URL(string: "path://\(stamp)")!)
linkAnn.setValue(stamp, forAnnotationKey: PDFAnnotationKey.init(rawValue: "_Path"))
linkAnn.backgroundColor = UIColor.yellow
self.currentPage?.addAnnotation(linkAnn)
self.drawView.removeFromSuperview()
self.closeBtn.isEnabled = false
self.saveBtn.isEnabled = false
self.undoBtn.isEnabled = false
self.pencil.isEnabled = true
}
func allButtons() -> [(PDFAnnotation,PDFPage)]{
var list = [(PDFAnnotation,PDFPage)]()
let checkType = PDFAnnotationSubtype.widget.rawValue.replacingOccurrences(of: "/", with: "");
for page in self.pdfView.visiblePages() {
for ann in page.annotations {
if ann.type! == checkType && ann.widgetFieldType == .button {
list.append((ann, page))
}
}
}
return list
}
func allLinks() -> [PDFAnnotation]{
var list = [PDFAnnotation]()
let checkType = PDFAnnotationSubtype.ink.rawValue.replacingOccurrences(of: "/", with: "");
for page in self.pdfView.visiblePages() {
for ann in page.annotations {
if ann.type! == checkType {
list.append(ann)
}
}
}
return list
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have a form in which I am displaying User existing data in Textfield and there is a profile image upload option as well. So lets say If I edit some fields in the textbox and then upload image from using imagePicker, then the data resets and it shows the old values. I don't know how can I fix this
My Code is this :-
class ProfileVC: UIViewController, TopViewDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UITextFieldDelegate {
#IBOutlet weak var topView: WATopView!
#IBOutlet weak var firstName: WATextField!
#IBOutlet weak var lastName: WATextField!
#IBOutlet weak var email: WATextField!
// #IBOutlet weak var password: WATextField!
#IBOutlet weak var university: WATextField!
#IBOutlet weak var graduationDate: WATextField!
#IBOutlet weak var major: WATextField!
#IBOutlet weak var homeTown: WATextField!
#IBOutlet weak var industry: WATextField!
#IBOutlet var profileImageView: WAImageView!
#IBOutlet weak var imagePickerButton:WAButton!
var pickerView = UIPickerView()
var uniList = [University]()
var industryList = [Industry]()
var selectedIndustry: Industry?
var selectedUni: University?
let imagePicker = UIImagePickerController()
var base64StringOf_my_image = String()
var prepCompressedImage: UIImage!
var isDismissing: Bool = false
let currentUser = User.getCurrentUser()
var inputViews = UIView()
let datePickerView = UIDatePicker()
let profileLoader = ProfileLoader()
override func viewDidLoad() {
super.viewDidLoad()
if fireNotification.pickedImage != nil {
profileImageView.image = fireNotification.pickedImage!.circle
self.prepCompressedImage = UIImage.compressImage(fireNotification.pickedImage, compressRatio: 0.9)
base64StringOf_my_image = appUtility.base64StringOfImage(self.prepCompressedImage)
fireNotification.pickedImage = nil
}else {
profileImageView.sd_setImageWithURL(NSURL(string: currentUser!.userImageURL), placeholderImage: UIImage(named:"no-image"))
self.prepCompressedImage = UIImage.compressImage(profileImageView.image, compressRatio: 0.9)
base64StringOf_my_image = appUtility.base64StringOfImage(self.prepCompressedImage)
}
pickerView.delegate = self
pickerView.dataSource = self
loadIndAndUni()
topView.delegate = self
disableEditing(false)
if !(currentUser?.firstName.isEmpty)! {
firstName.text = currentUser?.firstName
}
if !(currentUser?.lastName.isEmpty)! {
lastName.text = currentUser?.lastName
}
if !(currentUser?.email.isEmpty)! {
email.text = currentUser?.email
}
if !(currentUser?.uni_name.isEmpty)! {
university.text = currentUser?.uni_name
}
if !(currentUser?.startGradDate.isEmpty)! {
graduationDate.text = currentUser?.startGradDate
}
if !(currentUser?.major.isEmpty)! {
major.text = currentUser?.major
}
if !(currentUser?.homeTown.isEmpty)! {
homeTown.text = currentUser?.homeTown
}
if !(currentUser?.ind_name.isEmpty)! {
industry.text = currentUser?.ind_name
}
imagePickerButton.userInteractionEnabled = false
}
func loadIndAndUni(){
if fireNotification.uniList != nil {
uniList = fireNotification.uniList!
}else { self.loadUni()}
if fireNotification.indList != nil {
industryList = fireNotification.indList!
}else {self.loadIndustries()}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func editDoneButtonAction(sender: UIButton) {
if sender.titleLabel?.text == "Edit" {
topView.doneText = "Done"
// PrepUtility.showAlertWithTitle("Edit", error: "You are going to submit data", OKButton: "Edit", VC: self)
imagePickerButton.userInteractionEnabled = true
disableEditing(true)
}
if sender.titleLabel?.text == "Done" {
// PrepUtility.showAlertWithTitle("Done", error: "You are going to submit data", OKButton: "Done", VC: self)
submitRequest()
topView.doneText = "Edit"
disableEditing(false)
}
}
func submitRequest(){
let (isValid , error) = validateFields()
if !isValid {
appUtility.showAlert(error!,VC: self)
return
}
if (base64StringOf_my_image.isEmpty) {
appUtility.showAlert("Please Select Image",VC: self)
return
}
if PrepUtility.connectedToNetwork() {
appUtility.loadingView(self, isHide: false)
if selectedUni != nil {
let indText = industry.text
var selectedI: Industry?
for t in industryList {
if t.ind_name == indText {
selectedI = t
}
}
let params = ["std_id":currentUser!.std_id,"std_f_name":firstName.text!,"std_l_name":lastName.text!,"std_grad_date":graduationDate.text!,"std_hometown":homeTown.text!,"std_major":major.text!,"uni_id":selectedUni!.uni_id,"std_img":["content_type": "image/png", "filename":"test.png", "file_data": base64StringOf_my_image],"ind_id":selectedI!.ind_id]
editProfile(params)
}else {
let uniText = university.text
var selectedU: University?
for t in uniList {
if t.uni_name == uniText {
selectedU = t
}
}
let indText = industry.text
var selectedI: Industry?
for t in industryList {
if t.ind_name == indText {
selectedI = t
}
}
if selectedU!.uni_id.boolValue {
let params = ["std_id":currentUser!.std_id,"std_f_name":firstName.text!,"std_l_name":lastName.text!,"std_grad_date":graduationDate.text!,"std_hometown":homeTown.text!,"std_major":major.text!,"uni_id":selectedU!.uni_id,"std_img":["content_type": "image/png", "filename":"test.png", "file_data": base64StringOf_my_image],"ind_id":selectedI!.ind_id]
editProfile(params)
}
}
}else {
appUtility.loadingView(self, isHide: true)
appUtility.showNoNetworkAlert()
}
}
func editProfile(params:[String:AnyObject]) {
profileLoader.tryStudentProfileEdit(params, successBlock: { (user) in
appUtility.loadingView(self, isHide: true)
}, failureBlock: { (error) in
// appUtility.showAlert((error?.userInfo["NSLocalizedDescription"])! as! String, VC: self)
if let err = error?.userInfo["NSLocalizedDescription"] {
appUtility.showAlert(err as! String, VC: self)
appUtility.loadingView(self, isHide: true)
}else {
appUtility.loadingView(self, isHide: true)
appUtility.showAlert("Something went wrong", VC: self)
}
})
}
func openMenu() {
firstName.resignFirstResponder()
lastName.resignFirstResponder()
// email.resignFirstResponder()
// password.resignFirstResponder()
university.resignFirstResponder()
graduationDate.resignFirstResponder()
major.resignFirstResponder()
homeTown.resignFirstResponder()
industry.resignFirstResponder()
self.mainSlideMenu().openLeftMenu()
}
//MARK:- Private Methods
private func validateFields() -> (Bool , String?) {
if !firstName.isValid() {
hideView()
return (false , "Please enter your First Name")
}
if !lastName.isValid() {
hideView()
return (false , "Please enter your Last Name")
}
// if !email.isValid() {
// hideView()
// return (false , "Please enter email")
// }
//
// if email.isValid() {
// hideView()
// let text = email.text
// if !(text!.hasSuffix(".edu")) {
// return (false , "Please enter email that having .edu")
// }
// if !email.text!.isValidEmail() {
// return (false , "Please Enter a valid email...")
// }
// }
if !university.isValid() {
hideView()
// return (false , "Please select University")
}
if !homeTown.isValid() {
hideView()
// return (false , "Please enter address")
}
// if !password.isValid() {
// return (false , "Please enter password")
// }
//
return (true , nil)
}
private func showGradDatePicker() {
//Create the view
graduationDate.inputView = inputViews
inputViews = UIView(frame: CGRectMake(0, self.view.frame.height, self.view.frame.width, 240))
inputViews.backgroundColor = UIColor.whiteColor()
let datePickerView : UIDatePicker = UIDatePicker(frame: CGRectMake(0, 40, 0, 0))
datePickerView.datePickerMode = UIDatePickerMode.Date
inputViews.addSubview(datePickerView) // add date picker to UIView
let doneButton = UIButton(frame: CGRectMake((self.view.frame.size.width/2) - (100/2), 0, 100, 50))
doneButton.setTitle("Done", forState: UIControlState.Normal)
doneButton.setTitle("Done", forState: UIControlState.Highlighted)
doneButton.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
doneButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Highlighted)
inputViews.addSubview(doneButton) // add Button to UIView
doneButton.addTarget(self, action: #selector(ScheduleVC.doneButton(_:)), forControlEvents: UIControlEvents.TouchUpInside) // set button click event
// sender.inputView = inputView
datePickerView.addTarget(self, action: #selector(ScheduleVC.datePickerValueChanged(_:)), forControlEvents: UIControlEvents.ValueChanged)
self.view.addSubview(inputViews)
datePickerValueChanged(datePickerView) // Set the date on start.
UIView.animateWithDuration(0.5) {
self.inputViews.frame = CGRect(x: 0, y: self.view.frame.height - 270, width: self.view.frame.width, height: 240)
}
}
func doneButton(sender:UIButton) {
hideView()
}
func hideView() {
UIView.animateWithDuration(0.9) {
self.inputViews.frame = CGRect(x: 0, y:0, width: self.view.frame.width, height: 240)
self.inputViews.removeFromSuperview()
}
}
func datePickerValueChanged(sender:UIDatePicker) {
// isDateSet = true
let dateFormatter = NSDateFormatter()
// dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
graduationDate.text = dateFormatter.stringFromDate(sender.date)
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == university {
self.resignFirstResponder(university)
industry.tag = 1
university.tag = 0
graduationDate.tag = 1
pickerViewToolBar(textField)
}
if textField == industry {
self.resignFirstResponder(industry)
industry.tag = 0
university.tag = 1
graduationDate.tag = 1
pickerViewToolBar(textField)
}
if textField == graduationDate{
industry.tag = 1
university.tag = 1
graduationDate.tag = 0
self.resignFirstResponder(graduationDate)
showGradDatePicker()
}
return true
}
private func disableEditing(boo: Bool) {
firstName.enabled = boo
lastName.enabled = boo
// email.enabled = boo
// password.enabled = boo
university.enabled = boo
graduationDate.enabled = boo
major.enabled = boo
homeTown.enabled = boo
industry.enabled = boo
}
private func resignFirstResponder(textField:UITextField) {
if textField != firstName {
// hideView()
textField.resignFirstResponder()
}
if textField != lastName {
// hideView()
textField.resignFirstResponder()
}
// if textField != email{
//// hideView()
// textField.resignFirstResponder()
// }
// if textField != password {
//// hideView()
// textField.resignFirstResponder()
// }
if textField != university {
// hideView()
textField.resignFirstResponder()
}
if textField != graduationDate {
textField.resignFirstResponder()
}
if textField != major {
// hideView()
textField.resignFirstResponder()
}
if textField != homeTown {
// hideView()
textField.resignFirstResponder()
}
if textField != industry {
// hideView()
textField.resignFirstResponder()
}
}
private func resignAllTextFields() {
firstName.resignFirstResponder()
}
//MARK:- Public Methods
func pickerViewToolBar(sender: UITextField) {
var doneButton:UIBarButtonItem?
if university.tag == 0 {
university.inputView = pickerView
}
if industry.tag == 0 {
industry.inputView = pickerView
}
if graduationDate.tag == 0 {
graduationDate.inputView = pickerView
}
// departureDatePickerView.datePickerMode = UIDatePickerMode.Date
// Sets up the "button"
// Creates the toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adds the buttons
if(sender.tag == 0){
// self.nextButton?.hidden = true
doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(PrepInfoVC.doneClick(_:)))
doneButton!.tag = 0
}
// else if(sender.tag == 2){
//// self.nextButton?.hidden = true
// doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(PrepInfoVC.doneClick(_:)))
// doneButton!.tag = 2
// }
let spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(PrepInfoVC.cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton!], animated: false)
toolBar.userInteractionEnabled = true
// Adds the toolbar to the view
if university.tag == 0 {
university.inputAccessoryView = toolBar
}
if industry.tag == 0 {
industry.inputAccessoryView = toolBar
}
if graduationDate.tag == 0 {
graduationDate.inputAccessoryView = toolBar
}
}
func doneClick(sender:UIBarButtonItem) {
if industry.tag == 0 {
selectedIndustry = industryList[pickerView.selectedRowInComponent(0)]
industry.text = selectedIndustry!.ind_name
industry.tag = 1
industry.resignFirstResponder()
}else{
selectedUni = uniList[pickerView.selectedRowInComponent(0)]
university.text = selectedUni!.uni_name
university.tag = 1
university.resignFirstResponder()
}
}
func cancelClick() {
if industry.tag == 0 {
industry.tag = 1
industry.resignFirstResponder()
}else {
university.tag = 1
university.resignFirstResponder()
}
}
//MARK:- ImagePicker
#IBAction func loadImageButtonTapped(sender: UIButton) {
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
imagePicker.allowsEditing = true
imagePicker.delegate = self
self.hidesBottomBarWhenPushed = true
self.navigationController?.presentViewController(imagePicker, animated: true, completion: nil)
self.hidesBottomBarWhenPushed = false
}
// MARK: - UIImagePickerControllerDelegate Methods
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
print(info)
if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
profileImageView.image = pickedImage.circle
self.prepCompressedImage = UIImage.compressImage(pickedImage, compressRatio: 0.9)
base64StringOf_my_image = appUtility.base64StringOfImage(self.prepCompressedImage)
// self.viewWillAppear(false)
fireNotification.pickedImage = pickedImage
isDismissing = true
}else{}
imagePicker.delegate = nil
self.dismissViewControllerAnimated(true,completion: nil)
isDismissing = true
}
}
extension ProfileVC: UIPickerViewDelegate,UIPickerViewDataSource {
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
if university.tag == 0 {
return 1
}else {
return 1
}
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if university.tag == 0 {
return uniList.count
}
else {
return industryList.count
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if university.tag == 0 {
let uni = uniList[row]
return String(uni.uni_name)
}else {
let ind = industryList[row]
return String(ind.ind_name)
}
}
}
//MARK:- SearchVC
extension ProfileVC {
func loadUni() {
let userLoader = UserLoader()
let params = ["":""]
if PrepUtility.connectedToNetwork() {
userLoader.tryUniversity(params, successBlock: { (university) in
self.uniList = university!
}) { (error) in
if let err = error?.userInfo["NSLocalizedDescription"] {
appUtility.showAlert(err as! String, VC: self)
}else {
appUtility.showAlert("Something went wrong", VC: self)
}
}
}else {
appUtility.showNoNetworkAlert()
}
}
func loadIndustries() {
let userLoader = UserLoader()
if PrepUtility.connectedToNetwork() {
userLoader.tryIndustry(["":""], successBlock: { (industry) in
self.industryList = industry!
}) { (error) in
if let err = error?.userInfo["NSLocalizedDescription"] {
appUtility.showAlert(err as! String, VC: self)
}else {
appUtility.showAlert("Something went wrong", VC: self)
}
}
}else {
appUtility.showNoNetworkAlert()
}
}
}
Since you don't initialize your UI in a viewWillLoad or similar method, I would say that your issue is coming from your device trying to get some more space.
You are probably out of memory and the system kill what it can (in your case your previous controller).
When you dismiss the image picker, your controller is reloading its views (with your initial values)
i personally would save the .text of the label into variables previously declared (you are going to need them anyway) and in the viewDidAppear method assign the variables values to the textField.Text, when the view appear the first time they will appear empty, when you call the image picker you save the new values and then when the original view appears again it will assing the values you saved before.