How to get the right position of an View for animations? - ios

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
}
}
}

Related

Image change on button is not reflecting in iOS swift by using for loop

I have a situation where 9 buttons are placed on viewController and making tic-tac-toe function on ios. whenever I am trying to reset button images once the game is finished, button images are not getting reset.
class TicTacToeViewController: UIViewController {
#IBOutlet weak var gameBoardView: UIView!
#IBOutlet var buttons: [UIButton]!
var viewModel = TicTacToeViewModel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
func configureUI() {
viewModel.delegate = self
}
#IBAction func buttonClicked(_ sender: UIButton) {
viewModel.processPlayerMove(for: sender.tag)
}
/// This **function is to reset the view means remove close and circle image once player wants to restart the game. But this code is not working**
func updateButtonView() {
DispatchQueue.main.async {
for (index, moves) in self.viewModel.moves.enumerated() {
let button = self.buttons[index]
if let moves = moves {
let image = UIImage(named: moves.indicator)
button.setImage(image, for: .normal)
} else {
button.setImage(nil, for: .normal)
}
}
}
}
}
/// Delegates are called from viewmodel
extension TicTacToeViewController: TicTacToeViewModelProtocol {
func updatePlayerInfo(index: Int) {
let systemImageName = viewModel.moves[index - 1]?.indicator ?? ""
let image = UIImage(named: systemImageName)
if let arrayButtons = buttons {
let button = arrayButtons[index - 1]
button.setImage(image, for: .normal)
}
}
func displayAlert(alertData: AlertItem) {
let alert = UIAlertController(title: alertData.title, message: alertData.message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: alertData.buttonTitle, style: UIAlertAction.Style.default, handler: { [weak self] _ in
self?.viewModel.resetGame()
self?.updateButtonView()
}))
self.present(alert, animated: true, completion: nil)
}
func gameBoardDisabled(isGameBoardDisable: Bool) {
gameBoardView.isUserInteractionEnabled = !isGameBoardDisable
}
}
Please let me know of any confusion. Thanks in advance for your help.
This is view model class
import Foundation
protocol TicTacToeViewModelProtocol: AnyObject {
func updatePlayerInfo(index: Int)
func displayAlert(alertData: AlertItem)
func gameBoardDisabled(isGameBoardDisable: Bool)
}
enum Player {
case human
case computer
}
class TicTacToeViewModel {
var currentMovePosition: Int?
var moves: [Move?] = Array(repeating: nil, count: 9) {
didSet {
if let delegate = delegate, let position = self.currentMovePosition {
delegate.updatePlayerInfo(index: position)
}
}
}
var isGameBoardDisable = false {
didSet {
if let delegate = delegate {
delegate.gameBoardDisabled(isGameBoardDisable: isGameBoardDisable)
}
}
}
var alertItem: AlertItem? {
didSet {
if let delegate = delegate, let alertItem = alertItem {
delegate.displayAlert(alertData: alertItem)
}
}
}
let winPatterns: Set<Set<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]
weak var delegate: TicTacToeViewModelProtocol!
func processPlayerMove(for position: Int) {
self.currentMovePosition = position
if isSquareOccupied(in: moves, forIndex: position) { return }
moves[position - 1] = Move(player: .human, boardIndex: position)
// logic for win, draw or lose
if checkWinCondition(for: .human, in: moves) {
alertItem = AlertContext.humanWin
return
}
if checkForDraw(in: moves) {
alertItem = AlertContext.draw
return
}
isGameBoardDisable = true
processComputerMove()
}
func processComputerMove() {
let computerPosition = determinComputerMovePosition(in: moves)
self.currentMovePosition = computerPosition
moves[computerPosition - 1] = Move(player: .computer, boardIndex: computerPosition)
isGameBoardDisable = false
if checkWinCondition(for: .computer, in: moves) {
alertItem = AlertContext.computerWin
return
}
if checkForDraw(in: moves) {
alertItem = AlertContext.draw
return
}
}
func isSquareOccupied(in moves:[Move?], forIndex index: Int) -> Bool {
return moves.contains(where: { $0?.boardIndex == index })
}
func determinComputerMovePosition(in moves: [Move?]) -> Int {
let computerMoves = moves.compactMap { $0 }.filter { $0.player == .computer }
let computerPositions = Set(computerMoves.map { $0.boardIndex })
for pattern in winPatterns {
let winPositions = pattern.subtracting(computerPositions)
if winPositions.count == 1 {
let isAvailable = !isSquareOccupied(in: moves, forIndex: winPositions.first!)
if isAvailable { return winPositions.first! }
}
}
// if the AI ​​can't finish the game it will block
let humanMoves = moves.compactMap { $0 }.filter { $0.player == .human }
let humanPositions = Set(humanMoves.map { $0.boardIndex })
for pattern in winPatterns {
let winPositions = pattern.subtracting(humanPositions)
if winPositions.count == 1 {
let isAvailable = !isSquareOccupied(in: moves, forIndex: winPositions.first!)
if isAvailable { return winPositions.first! }
}
}
// always take the middle block
let middleSquare = 5
if !isSquareOccupied(in: moves, forIndex: middleSquare) {
return middleSquare
}
// if the AI ​​can't get position middle block it will get a random position
var movePosition = Int.random(in: 1..<10)
while isSquareOccupied(in: moves, forIndex: movePosition) {
movePosition = Int.random(in: 1..<10)
}
return movePosition
}
func checkWinCondition(for player: Player, in moves:[Move?]) -> Bool {
let playerMoves = moves.compactMap({ $0 }).filter { $0.player == player }
let playerPositions = Set(playerMoves.map { $0.boardIndex })
for pattern in winPatterns where pattern.isSubset(of: playerPositions) {return true}
return false
}
func checkForDraw(in moves: [Move?]) -> Bool {
return moves.compactMap { $0 }.count == 9
}
func resetGame() {
moves = Array(repeating: nil, count: 9)
}
}

How to check if every two flipped cards' current title of their buttons in an array are matching in a card matching game

I am adding in some functionalities for this iOS swift matching card game and I need to check if the first 2 buttons flipped over match. They have four types of emojis for eight cards, which means there are 4 pairs of matches. I am having trouble finding out how to check if the cards match and when they match, I need the background color of the buttons to opaque (invisible). Everything else works except the empty if statement in the concentration class within the chooseCard function. That is where I need help.
Here's all the code so you can see whats related to what:
class ViewController: UIViewController {
lazy var game = Concentration(numberOfPairsOfCards: (cardButtons.count + 1) / 2)
var flipCount = 0 {
// Property Observer
didSet { flipLabel.text = "Flips: \(flipCount)" }
}
#IBOutlet weak var flipLabel: UILabel!
#IBOutlet var cardButtons: [UIButton]!
#IBAction func touchCard(_ sender: UIButton) {
flipCount+=1
if let cardNumber = cardButtons.firstIndex(of: sender) {
game.chooseCard(at: cardNumber)
updateViewFromModel()
} else {
print ("chosen card was not in cardButtons")
}
}
var emojiChoices = ["👻", "🎃", "🙏🏾", "🦆"]
var emoji = [Int:String]()
func emoji(for card: Card) -> String {
if emoji[card.identifier] == nil, emojiChoices.count > 0 {
let randomIndex = Int(arc4random_uniform(UInt32(emojiChoices.count)))
emoji[card.identifier] = emojiChoices.remove(at: randomIndex)
}
return emoji[card.identifier] ?? "?"
}
func updateViewFromModel() {
for index in cardButtons.indices {
let button = cardButtons[index]
let card = game.cards[index]
if card.isFaceUp {
button.setTitle(emoji(for: card), for: UIControl.State.normal)
button.backgroundColor = UIColor.white
}
else {
button.setTitle("", for: UIControl.State.normal)
button.backgroundColor = UIColor.orange
}
}
}
}
import Foundation
class Concentration {
var cards = [Card]()
func chooseCard(at index: Int) {
if cards[index].isFaceUp {
cards[index].isFaceUp = false
}
else {
cards[index].isFaceUp = true
}
if cards[index].isFaceUp && cards[index].isMatched {
}
}
init(numberOfPairsOfCards: Int) {
for _ in 0..<numberOfPairsOfCards {
let card = Card()
cards += [card,card]
}
//TODO: Shuffle cards
cards.shuffle()
}
}
import Foundation
struct Card {
var isMatched = false
var isFaceUp = false
var identifier: Int
static var identifierFactory = 0
static func getUniqueIdentifier() -> Int {
Card.identifierFactory += 1
return Card.identifierFactory
}
init() {
self.identifier = Card.getUniqueIdentifier()
}
}
In your concentration class you will check for faceUp card indexes
Change your Concentration from class to Struct
struct Concentration { // instead of class Concentration
private var indexOfFaceUpCard: Int? {
get {
let faceUpCardIndices = cards.indices.filter { cards[$0].isFaceUp }
return faceUpCardIndices.count == 1 ? faceUpCardIndices.first : nil
} set {
for index in cards.indices {
cards[index].isFaceUp = (index == newValue)
}
}
}
Then you have mutating chooseCard method
mutating func chooseCard(at index: Int)
In your chooseCard method you check for matching
if !cards[index].isMatched {
if let matchIndex = indexOfFaceUpCard, matchIndex != index {
if cards[matchIndex] == cards[index] {
cards[matchIndex].isMatched = true
cards[index].isMatched = true
}
cards[index].isFaceUp = true
} else {
indexOfFaceUpCard = index
}
}
So your method look like this
mutating func chooseCard(at index: Int) {
if !cards[index].isMatched {
if let matchIndex = indexOfFaceUpCard, matchIndex != index {
if cards[matchIndex] == cards[index] {
cards[matchIndex].isMatched = true
cards[index].isMatched = true
}
cards[index].isFaceUp = true
} else {
indexOfFaceUpCard = index
}
}
}
Update your card struct
struct Card: Hashable {
var isMatched = false
var isFaceUp = false
var identifier: Int
static var identifierFactory = 0
static func getUniqueIdentifier() -> Int {
Card.identifierFactory += 1
return Card.identifierFactory
}
static func ==(lhs: Card, rhs: Card) -> Bool {
return lhs.identifier == rhs.identifier
}
init() {
self.identifier = Card.getUniqueIdentifier()
}
}

how i can add a text on pdf?

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.
}
}

TextField Values reset after returning from the Image Picker

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.

complateTransition don't dismiss the from view swift 2

I am trying to set an interactive transition with this class :
class TransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning, UIViewControllerTransitioningDelegate, UIViewControllerContextTransitioning {
weak var transitionContext: UIViewControllerContextTransitioning?
var sourceViewController: UIViewController! {
didSet {
enterPanGesture = UIScreenEdgePanGestureRecognizer()
enterPanGesture.addTarget(self, action:"panned:")
enterPanGesture.edges = UIRectEdge.Left
sourceViewController.view.addGestureRecognizer(enterPanGesture)
}
}
var togoSourceViewController: UIViewController!
let duration = 1.0
var presenting = true
var reverse = false
var originFrame = CGRectNull
var shouldBeInteractive = false
private var didStartedTransition = false
private var animated = false
private var interactive = false
private var AnimationStyle = UIModalPresentationStyle(rawValue: 1)
private var didFinishedTransition = false
private var percentTransition: CGFloat = 0.0
private var enterPanGesture: UIScreenEdgePanGestureRecognizer!
private var tovc = UIViewController()
private var pointtovc = CGPoint()
private var pointfromvc = CGPoint()
private var fromvc = UIViewController()
private var generalcontainer = UIView()
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
animated = true
let container = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
if reverse {
toViewController.view.center.x -= (container?.bounds.size.width)!
container?.insertSubview(toViewController.view, aboveSubview: fromViewController.view)
} else {
toViewController.view.center.x += (container?.bounds.size.width)!
container?.addSubview(toViewController.view)
}
UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.TransitionNone, animations: {
if self.reverse {
toViewController.view.center.x += (container?.bounds.size.width)!
} else {
toViewController.view.center.x -= (container?.bounds.size.width)!
}
}, completion: { finished in
transitionContext.completeTransition(true)
self.animated = false
self.reverse = !self.reverse
})
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return duration
}
func startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning) {
interactive = true
animated = true
let container = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)! //ArticleView
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! //Article OU Favoris
if reverse {
toViewController.view.frame.origin.x = -fromViewController.view.frame.maxX
container?.insertSubview(toViewController.view, aboveSubview: fromViewController.view)
}
tovc = toViewController
pointtovc = toViewController.view.bounds.origin
fromvc = fromViewController
pointfromvc = fromViewController.view.bounds.origin
generalcontainer = container!
}
func containerView() -> UIView? {
return sourceViewController?.view
}
func viewControllerForKey(key: String) -> UIViewController? {
return sourceViewController?.storyboard!.instantiateViewControllerWithIdentifier(key)
}
func viewForKey(key: String) -> UIView? {
return sourceViewController?.storyboard!.instantiateViewControllerWithIdentifier(key).view
}
func initialFrameForViewController(vc: UIViewController) -> CGRect {
return vc.view.frame
}
func finalFrameForViewController(vc: UIViewController) -> CGRect {
return vc.view.frame
}
func isAnimated() -> Bool {
return animated
}
func isInteractive() -> Bool {
return interactive
}
func presentationStyle() -> UIModalPresentationStyle {
return AnimationStyle!
}
func completeTransition(didComplete: Bool) {
interactive = false
animated = false
shouldBeInteractive = false
didFinishedTransition = didComplete
transitionContext?.finishInteractiveTransition()
transitionContext?.completeTransition(true)
}
func updateInteractiveTransition(percentComplete: CGFloat) {
if self.reverse {
print(percentComplete)
self.tovc.view.frame.origin.x = (self.fromvc.view.frame.maxX * (percentComplete)) - self.fromvc.view.frame.maxX
}
}
func finishInteractiveTransition() {
UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.TransitionNone, animations: {
if self.reverse {
self.tovc.view.frame.origin.x = self.fromvc.view.frame.origin.x
}
}, completion: { finished in
self.animated = false
self.reverse = !self.reverse
self.completeTransition(true)
})
}
func cancelInteractiveTransition() {
UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.TransitionNone, animations: {
if self.reverse {
self.tovc.view.frame.origin.x = -self.fromvc.view.frame.maxX
}
}, completion: { finished in
self.animated = false
self.completeTransition(true)
})
}
func transitionWasCancelled() -> Bool {
return didFinishedTransition
}
func targetTransform() -> CGAffineTransform {
return CGAffineTransform()
}
func completionSpeed() -> CGFloat {
return 1 - percentTransition
}
func panned(pan: UIPanGestureRecognizer) {
switch pan.state {
case .Began:
animated = true
shouldBeInteractive = true
didStartedTransition = true
didFinishedTransition = false
sourceViewController?.dismissViewControllerAnimated(true, completion: nil)
updateInteractiveTransition(0)
break
case .Changed:
percentTransition = CGFloat(pan.translationInView(sourceViewController!.view).x / sourceViewController!.view.frame.width)
if percentTransition < 0.0 {
percentTransition = 0.0
} else if percentTransition > 1.0 {
percentTransition = 1.0
}
updateInteractiveTransition(percentTransition)
break
case .Ended, .Failed, .Cancelled:
animated = false
shouldBeInteractive = false
didStartedTransition = false
didFinishedTransition = true
if percentTransition < 0.8 {
cancelInteractiveTransition()
} else {
finishInteractiveTransition()
}
break
case .Possible:
break
}
}
}
The animateTransition works perfectly and dismiss my fromViewController but during my InteractiveTransition when I call finishInteractiveTransition() and then completeTransition(true), I still have my both view :
But on Apple they said :
You must call this method after your animations have completed to notify the system that the transition animation is done. The parameter you pass must indicate whether the animations completed successfully. For interactive animations, you must call this method in addition to the finishInteractiveTransition or cancelInteractiveTransition method. The best place to call this method is in the completion block of your animations.
So, what am I doing wrong ?
I am using ios9, swift 2, Xcode 7 beta 6
I found the solution :
i should call transitionContext.completeTransition(true) in function finishInteractiveTransition() but on my previous code transitionContext was not the same that in startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning)
So i add one variable :
private var Context: UIViewControllerContextTransitioning?
and use this to call :
transitionContext.completeTransition(true)
or
transitionContext.completeTransition(false)

Resources