my app part is based on canvas.
#What I want to do?
I need dictionary to track and save particular player's key and value.because, I want to store player1 on key "1" and player2 on key "2", suppose user change player 2's number, then player 2's number change not key "2".
I can place multiple players (cashapelayers - with text), on imageview. and can edit text label on double click for same player.
my issue is, whenever i click second time on same player, it shows wrong number, as well when click okay it creates new player. what i want is to edit a player's label(number) with different number, and don't create a new one till I click on imageview.
I have try to create playerview in touchedEnded but I'm fail, also try to search for the same issue on other resources.
I have added some images for reference.
class AddPlayerStruct {
var addPlayerViewStruct : AddPlayerView?
var addPlayerViewsArrStruct : [AddPlayerView] = []
var Label = UILabel()
}
import UIKit
class ViewController: UIViewController {
//MARK: AddPlayerView Variables
var addPlayerView : AddPlayerView?
var addPlayerViews: [AddPlayerView] = []
var draggedAddPlayer: AddPlayerView?
let addPlayerWidth : CGFloat = 40
var addPlayerDict : [String : AddPlayerStruct] = [:]
var playerCount : Int = 1
var label = UILabel()
var isDobuleClick : Bool = false
@IBOutlet weak var images: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let draggedAddPlayer = draggedAddPlayer, let point = touches.first?.location(in: images) else {
return
}
draggedAddPlayer.center = point
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Do nothing if a circle is being dragged
// or if we do not have a coordinate
guard draggedAddPlayer == nil, let point = touches.first?.location(in: images) else {
return
}
// Do not create new circle if touch is in an existing circle
// Keep the reference of the (potentially) dragged circle
if let draggedAddPlayer = addPlayerViews.filter({ UIBezierPath(ovalIn: $0.frame).contains(point) }).first {
self.draggedAddPlayer = draggedAddPlayer
return
}
// Create new circle and store in dict
let rect = CGRect(x: point.x - 20, y: point.y - 20, width: addPlayerWidth, height: addPlayerWidth)
addPlayerView = AddPlayerView(frame: rect)
addPlayerView?.backgroundColor = .white
addPlayerView?.isUserInteractionEnabled = true
addPlayerView?.image = UIImage(named: "player")
addPlayerView?.tintColor = .systemBlue
addPlayerViews.append(addPlayerView!)
images.addSubview(addPlayerView!)
// The newly created view can be immediately dragged
draggedAddPlayer = addPlayerView
//Add Player label as Number
// playerCount = addPlayerDict.count + 1
var addPlayerStruct = AddPlayerStruct()
label = UILabel(frame: CGRect(x: rect.width / 2 - 8, y: rect.height / 2 + 5, width: 16, height: 10))
if addPlayerStruct.Label.text == nil{
label.text = String(addPlayerDict.count + 1)
}
label.font = UIFont(name: "Helvetica" , size: 10)
label.textColor = UIColor.white
label.textAlignment = NSTextAlignment.center
label.isUserInteractionEnabled = true
addPlayerView!.addSubview(label)
debugPrint(addPlayerDict)
addPlayerStruct.addPlayerViewStruct = addPlayerView
addPlayerStruct.addPlayerViewsArrStruct.append(contentsOf: addPlayerViews)
addPlayerDict.updateValue(addPlayerStruct, forKey: String(addPlayerDict.count + 1))
debugPrint(addPlayerDict)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
draggedAddPlayer = nil
var selectedPlayerKey = String()
var addPlayerStruct = AddPlayerStruct()
var selectedPoint = CGPoint()
if isDobuleClick == true {
guard let point = touches.first?.location(in: images) else {
return
}
//TODO: check which dict key's playerview has same point
addPlayerDict.forEach { (key,value) in
debugPrint(key)
debugPrint(value)
// debugPrint("before \(addPlayerDict.count)")
//TODO: get selected dict key and get all data of it
guard let points = value.addPlayerViewStruct?.frame.contains(point) else { return }
if points{
selectedPlayerKey = key
selectedPoint = point
addPlayerViews.append(contentsOf: value.addPlayerViewsArrStruct)
debugPrint(addPlayerViews.last)
addPlayerView = value.addPlayerViewStruct //selected playerview
debugPrint(selectedPlayerKey)
// show data on alertview textfield
let alert = UIAlertController(title: "Player Number", message: "Enter new player Number", preferredStyle: .alert)
alert.addTextField { textData in
if addPlayerStruct.Label.text == nil{
textData.text = selectedPlayerKey
}else{
textData.text = addPlayerStruct.Label.text
}
}
// get changed data from textfield and save back to same dict key's playerview - Don't change key.
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
let textfield = alert.textFields?[0]
addPlayerStruct.Label.text = textfield?.text!
// let index = self.addPlayerDict.index(forKey: selectedPlayerKey)
addPlayerStruct.addPlayerViewStruct = self.addPlayerView
self.draggedAddPlayer = self.addPlayerView
self.addPlayerViews.removeLast()
self.addPlayerView?.removeFromSuperview() //selected playerview removed from iamgeview
//
// // Show on playerview
//
let rect = CGRect(x: selectedPoint.x - 20, y: selectedPoint.y - 20, width: self.addPlayerWidth, height: self.addPlayerWidth)
self.addPlayerView = AddPlayerView(frame: rect)
self.addPlayerView?.backgroundColor = .white
self.addPlayerView?.isUserInteractionEnabled = true
self.addPlayerView?.image = UIImage(named: "player")
self.addPlayerView?.tintColor = .systemBlue
self.addPlayerViews.append(self.addPlayerView!)
self.images.addSubview(self.addPlayerView!)
self.label = UILabel(frame: CGRect(x: rect.width / 2 - 8, y: rect.height / 2 + 5, width: 16, height: 10))
self.label.text = textfield?.text!
self.label.font = UIFont(name: "Helvetica" , size: 10)
self.label.textColor = UIColor.white
self.label.textAlignment = NSTextAlignment.center
self.label.isUserInteractionEnabled = true
self.addPlayerView!.addSubview(self.label)
debugPrint(self.addPlayerDict.count)
self.addPlayerDict.updateValue(addPlayerStruct, forKey: selectedPlayerKey)
debugPrint(addPlayerStruct.addPlayerViewStruct?.frame)
debugPrint(self.addPlayerDict.count)
}))
self.present(alert, animated: false)
}
}
}
isDobuleClick = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
self.isDobuleClick = false
}
}
}
#AddPlayerView
class AddPlayerView : UIImageView{
var shapeLayer = CAShapeLayer()
var addPlayerPath = UIBezierPath()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
self.backgroundColor = .clear
// let shapeLayer = CAShapeLayer()
addPlayerPath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2, y: frame.size.height / 2), radius: 20, startAngle: 0, endAngle: 360, clockwise: true)
shapeLayer.path = addPlayerPath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
self.layer.addSublayer(shapeLayer)
}
}