Related
I wrote the code base on Apple's example,
somehow the app will crash if accessing the setter of the custom entity component (the reveal() method)
I tried to initialize the component to see what will happen, but it crashed at anchor.addChild(card) (ViewController line 89) instead.
But it runs without any problem on iPadOS 14 which makes it even weirder.
Does anyone know why it happens and how to fix it?
my code
// CardEntity.swift
// Card-Game
//
// Created by Ian Liu on 2020/7/21.
//
import Foundation
import RealityKit
class CardEntity: Entity, HasModel, HasCollision {
required init() {
super.init()
self.components[ModelComponent] = ModelComponent(
mesh: .generateBox(width: 0.09, height: 0.005, depth: 0.09),
materials: [SimpleMaterial(
color: .orange,
isMetallic: false)
]
)
}
var card: CardComponent {
get { components[CardComponent] ?? CardComponent() }
set { components[CardComponent] = newValue }
}
}
extension CardEntity {
func reveal() {
card.revealed = true
var transform = self.transform
transform.rotation = simd_quatf(angle: 0, axis: [1, 0, 0])
move(to: transform, relativeTo: parent, duration: 0.25, timingFunction: .easeInOut)
}
func hide() {
card.revealed = false
var transform = self.transform
transform.rotation = simd_quatf(angle: .pi, axis: [1, 0, 0])
move(to: transform, relativeTo: parent, duration: 0.25, timingFunction: .easeInOut)
}
}
// CardComponent.swift
// Card-Game
//
// Created by Ian Liu on 2020/7/21.
//
import Foundation
import RealityKit
struct CardComponent: Component, Codable {
var revealed = false
var id = -1
init() {
self.revealed = false
self.id = -1
}
}
//
// ViewController.swift
// Card-Game
//
// Created by 劉學逸 on 7/16/20.
//
import UIKit
import ARKit
import RealityKit
import Combine
class ViewController: UIViewController, ARSessionDelegate {
#IBOutlet var arView: ARView!
let cardCount = 16
var prevCard: CardEntity? = nil
override func viewDidLoad() {
super.viewDidLoad()
arView.center = self.view.center
arView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
arView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
arView.session.delegate = self
let config = ARWorldTrackingConfiguration()
if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentation) {
config.frameSemantics.insert(.personSegmentationWithDepth)
}
config.planeDetection = [.horizontal]
arView.session.run(config)
addCoachingOverlay()
let anchor = AnchorEntity(plane: .horizontal, minimumBounds: [0.2, 0.2])
arView.scene.addAnchor(anchor)
CardComponent.registerComponent()
var cards: [CardEntity] = []
var models: [Entity] = []
for index in 1...cardCount {
let cardModel = CardEntity()
cardModel.name = "card_\((index+1)/2)"
cardModel.card.id = (index+1)/2
cards.append(cardModel)
}
var cancellable: Cancellable? = nil
// will build for a long time if load 8 models
cancellable = ModelEntity.loadModelAsync(named: "memory_card_1")
.append(ModelEntity.loadModelAsync(named: "memory_card_2"))
.append(ModelEntity.loadModelAsync(named: "memory_card_3"))
.append(ModelEntity.loadModelAsync(named: "memory_card_4"))
.append(ModelEntity.loadModelAsync(named: "memory_card_5"))
.append(ModelEntity.loadModelAsync(named: "memory_card_6"))
.append(ModelEntity.loadModelAsync(named: "memory_card_7"))
.append(ModelEntity.loadModelAsync(named: "memory_card_8"))
.collect().sink(receiveCompletion: {error in
print("error: \(error)")
cancellable?.cancel()},
receiveValue: { entities in
for (index, entity) in entities.enumerated() {
entity.setScale(SIMD3<Float>(0.0025,0.0025,0.0025), relativeTo: anchor)
entity.position = entity.position + SIMD3<Float>(0, 0.0025, 0)
entity.name = "memory_card_\(index)"
for _ in 1...2 {
models.append(entity.clone(recursive: true))
}
}
for (index, card) in cards.enumerated() {
card.addChild(models[index])
}
cards.shuffle()
for card in cards {
var flipTransform = card.transform
flipTransform.rotation = simd_quatf(angle: .pi, axis: [1, 0, 0])
card.move(to: flipTransform, relativeTo: card.parent)
}
//attach cards to the anchor
for (index, card) in cards.enumerated() {
card.generateCollisionShapes(recursive: true)
let x = Float(index % Int(sqrt(Double(self.cardCount)))) - 1.5
let z = Float(index / Int(sqrt(Double(self.cardCount)))) - 1.5
card.position = [x * 0.1, 0, z * 0.1]
anchor.addChild(card)
}
cancellable?.cancel()
})
// Adding Occlusion Box
// Create box mesh, 0.7 meters on all sides
let boxSize: Float = 0.7
let boxMesh = MeshResource.generateBox(size: boxSize)
// Create Occlusion Material
let material = OcclusionMaterial()
// Create ModelEntity using mesh and materials
let occlusionBox = ModelEntity(mesh: boxMesh, materials: [material])
// Position box with top slightly below game board
occlusionBox.position.y = -boxSize / 2 - 0.001
// Add to anchor
anchor.addChild(occlusionBox)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
arView.center = view.center
centerCoachingView()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let configuration = arView.session.configuration else { return }
arView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
arView.session.pause()
}
#IBAction func onTap(_ sender: UITapGestureRecognizer) {
let tapLocation = sender.location(in: arView)
if let entity = arView.entity(at: tapLocation) {
var card = entity
if entity.name.hasPrefix("memory_card") {
card = entity.parent!
}
guard let cardEntity = card as? CardEntity else { return }
print("tapped card id: \(cardEntity.card.id)")
if cardEntity.card.revealed {
return
} else {
cardEntity.reveal()
}
if let lastCard = prevCard {
print("last card id: \(lastCard.card.id)")
if lastCard.card.id != cardEntity.card.id {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
cardEntity.hide()
lastCard.hide()
}
}
self.prevCard = nil
} else {
print("last card id: N\\A")
prevCard = cardEntity
}
}
}
}
extension ViewController: ARCoachingOverlayViewDelegate {
func addCoachingOverlay() {
let coachingOverlay = ARCoachingOverlayView()
coachingOverlay.autoresizingMask = [.flexibleHeight, .flexibleWidth]
coachingOverlay.center = view.center
coachingOverlay.delegate = self
coachingOverlay.session = arView.session
coachingOverlay.goal = .horizontalPlane
arView.addSubview(coachingOverlay)
NSLayoutConstraint.activate([
coachingOverlay.centerXAnchor.constraint(equalTo: view.centerXAnchor),
coachingOverlay.centerYAnchor.constraint(equalTo: view.centerYAnchor),
coachingOverlay.widthAnchor.constraint(equalTo: view.widthAnchor),
coachingOverlay.heightAnchor.constraint(equalTo: view.heightAnchor)
])
coachingOverlay.activatesAutomatically = true
}
//TODO: Fix coachingView won't center when first orientation change
func centerCoachingView() {
for subview in arView.subviews {
if let coachingView = subview as? ARCoachingOverlayView {
coachingView.center = self.view.center
}
}
}
}
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 want to create a set game App. For that, I have a deck of cards from which I want the cards to (animating) move on the board.
My problem is when I do this:
private func createDeck() {
allCards.forEach{ card in
card.isFaceUp = false
card.frame = Deck.frame
GameBoard.allCardsInDeck.append(card)
}
}
the cards appearing from another position then the deck.
Doesn´t Deck.frame give me the current position of the view in its superview? my card appearing from the top but my deckView is at the bottom.
this is my code ViewController:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var informationLabel: UILabel!
#IBOutlet weak var ScoreLabel: UILabel!
#IBOutlet weak var Deck: Deck!
#IBOutlet weak var GameBoard: CardBoardView! {
didSet {
let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipe))
swipeGesture.direction = .down
GameBoard.addGestureRecognizer(swipeGesture)
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotation))
GameBoard.addGestureRecognizer(rotationGesture)
}
}
private var gameIsStarted = false
private var game: Game = Game() {
didSet {
updateScoreLabel()
}
}
private var selectedCards = [CardSubview] ()
private var indexOfAllCards: Int = 0
private lazy var allCards = getAllCards()
private var cardsBackgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
#objc func rotation(recognizer: UIRotationGestureRecognizer){
switch recognizer.state {
case .ended: GameBoard.mixCards()
default: break
}
}
#objc private func swipe(recognizer: UISwipeGestureRecognizer) {
switch recognizer.state {
case .ended: add3Cards()
default: break
}
}
private func getAllCards () -> [CardSubview] {
var cards = [CardSubview]()
for index in 0..<game.cards.count {
cards.append(CardSubview())
cards[index].fill = game.cards[index].strokeIdentifier
cards[index].color = game.cards[index].colorIdentifier
cards[index].form = game.cards[index].form
cards[index].occurence = game.cards[index].occurenceOfForm
cards[index].addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tab)))
cards[index].backgroundColor = cardsBackgroundColor
cards[index].indexNr = index
}
return cards
}
#objc private func tab (recognizer: UITapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let card = recognizer.view as? CardSubview, card.isFaceUp == true {
card.isSelected = !card.isSelected
if card.isSelected {
selectedCards.append(card)
if selectedCards.count > 2 {
let isSet = game.isSet(arrayOfIndexes: [selectedCards[0].indexNr,selectedCards[1].indexNr, selectedCards[2].indexNr]) == true
if isSet {
game.score += 1
selectedCards.forEach { card in
GameBoard.doWhenMatched(card: card)
card.isSelected = false
selectedCards.removeAll()
}
findSet()
} else if isSet == false {
game.score -= 1
selectedCards.forEach{ card in
card.isSelected = false
}
selectedCards.removeAll()
}
}
} else if card.isSelected == false, selectedCards.contains(card) {
selectedCards.remove(at: selectedCards.index(of: card)!)
}
}
default: break
}
}
private func findSet() {
if GameBoard.allOpenCards.count > 0 {
var setInOpenCards = Bool()
var allSetsInOpenCards = Int()
for index1 in 0..<GameBoard.allOpenCards.count-2 {
for index2 in (index1+1)..<GameBoard.allOpenCards.count-1 {
for index3 in (index2+1)..<GameBoard.allOpenCards.count {
setInOpenCards = game.isSet(arrayOfIndexes: [allCards[index1].indexNr, allCards[index2].indexNr, allCards[index3].indexNr])
if (setInOpenCards == true){
allSetsInOpenCards+=1
}
}
}
}
informationLabel.text = "Sets available: \(allSetsInOpenCards)"
} else {
informationLabel.text = "Sets available: \(0)"
}
}
#IBAction private func newGame() {
game = Game()
GameBoard.removeSubviewsFromDeck()
GameBoard.allCardsInDeck.removeAll()
createDeck()
GameBoard.backgroundColor = UIColor.black
GameBoard.removeSubviews()
selectedCards.removeAll()
gameIsStarted = true
allCards = getAllCards()
indexOfAllCards = 0
GameBoard.allOpenCards.removeAll()
add12Cards()
}
private func updateScoreLabel () {
if game.score >= 0 {
ScoreLabel.backgroundColor = #colorLiteral(red: 0, green: 0.9768045545, blue: 0, alpha: 0.5)
} else if game.score < 0 {
ScoreLabel.backgroundColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 0.5)
}
ScoreLabel.text = "Score: \(game.score)"
}
private func add3Cards() {
if indexOfAllCards < allCards.count, gameIsStarted == true {
for _ in 0...2 {
GameBoard.allOpenCards.append(GameBoard.allCardsInDeck[indexOfAllCards])
indexOfAllCards+=1
}
}
findSet()
}
private func add12Cards() {
let numbersOfFirst12Cards = 12
if gameIsStarted == true {
for _ in 0..<numbersOfFirst12Cards {
GameBoard.allOpenCards.append(GameBoard.allCardsInDeck[indexOfAllCards])
indexOfAllCards += 1
}
}
findSet()
}
private func createDeck() {
allCards.forEach{ card in
card.isFaceUp = false
card.frame = Deck.frame
GameBoard.allCardsInDeck.append(card)
}
}
}
This is my CardBoardView where all my animations happening
import UIKit
#IBDesignable
class CardBoardView: UIView {
let durationForDisappearingCards = 2.0
let delayForDisappearingCards = 0.0
lazy var animator = UIDynamicAnimator(referenceView: self)
lazy var cardBehavior = CardBehavior(in: animator)
var allOpenCards = [CardSubview]() {
didSet { addSubview(); setNeedsLayout();}
}
var allCardsInDeck = [CardSubview] () {
didSet{ setNeedsLayout()}
}
struct Layout {
static let ratio:CGFloat = 2.0
static let insetByX:CGFloat = 2.0
static let insetByY:CGFloat = 2.0
}
private func addSubview() {
for card in allOpenCards {
addSubview(card)
}
}
public func removeSubviews() {
for card in allOpenCards {
card.removeFromSuperview()
}
}
public func removeSubviewsFromDeck() {
allCardsInDeck.forEach{ card in
card.removeFromSuperview()
}
}
public func mixCards() {
var mixCards = [CardSubview]()
for _ in 0..<allOpenCards.count {
let random = allOpenCards.count.arc4random
let card = allOpenCards[random]
mixCards.append(card)
allOpenCards.remove(at: random)
}
allOpenCards = mixCards
}
public func doWhenMatched(card: CardSubview) {
// cardBehavior.addItem(card)
UIView.animate(
withDuration: self.durationForDisappearingCards,
delay: self.delayForDisappearingCards,
animations: {
card.frame = CGRect(x: (self.superview?.frame.midX)!-card.bounds.width/2, y: (self.superview?.frame.minY)!-card.bounds.height, width: card.bounds.width , height: card.bounds.height)
}, completion: { finish in
card.removeFromSuperview()
self.allOpenCards.remove(at: self.allOpenCards.index(of: card)!)
}
)
}
// let newPosition = CGRect(x: self.frame.midX-card.bounds.width/2 , y: self.frame.minY, width: card.bounds.width, height: card.bounds.height)
//
//
//
// UIView.animate(withDuration: durationForDisappearingCards, delay: delayForDisappearingCards, options: [.allowUserInteraction], animations: {card.alpha=0.0})
override func layoutSubviews() {
super.layoutSubviews()
var grid = Grid(layout: .aspectRatio(Layout.ratio), frame: self.bounds)
grid.cellCount = allOpenCards.count
var secondsForDelay:CGFloat = 0
let secondsForFlipCard:CGFloat = 0.5
for index in allOpenCards.indices {
if self.allOpenCards[index].frame != (grid[index]?.insetBy(dx: Layout.insetByX, dy: Layout.insetByY)) ?? CGRect.zero {
UIView.animate(
withDuration: 0.5,
delay: TimeInterval(secondsForDelay) ,
animations: {self.allOpenCards[index].frame = (grid[index]?.insetBy(dx: Layout.insetByX, dy: Layout.insetByY)) ?? CGRect.zero},
completion: {
finish in
if self.allOpenCards[index].isFaceUp != true {
UIView.transition(with: self.allOpenCards[index],
duration: TimeInterval(secondsForFlipCard),
options: [.transitionFlipFromLeft],
animations: {
self.allOpenCards[index].isFaceUp = true
}
)
}
}
)
secondsForDelay+=0.02
}
}
}
}
private extension Int {
var arc4random: Int {
if self > 0 {
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
return -Int(arc4random_uniform(UInt32(self)))
} else {
return 0
}
}
}
private extension CGFloat {
var arc4random: CGFloat {
if self > 0 {
return CGFloat(arc4random_uniform(UInt32(self)))
} else if self < 0 {
return -CGFloat(arc4random_uniform(UInt32(self)))
} else {
return 0
}
}
}
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)
}
}
}
}
}
}
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.