Как и многие здешние читатели, я смотрел сессию WWDC 2017, посвященную новым методам перетаскивания, доступным в iOS 11.x, и с интересом размышлял о том, какое простое приложение я мог бы создать, чтобы получить некоторый практический опыт работы с эти новые методы.

Когда я играл в шахматы с моим сыном, у меня случился момент озарения. Я знаю, я думал, что пишу простую онлайн-игру в шахматы, приложение, которое потребует от меня перетаскивания изображений по экрану, в данном случае шахматных фигур. Итак, в воскресенье днем ​​я собрал это вместе и решил поделиться с вами историей в процессе.

Начнем с изображения, это была моя цель; и будет конечным результатом, если вам удастся следовать этому короткому руководству.

Это немного грубо по краям, но важна концепция/код. Конечно, на этом изображении этого не видно, но вы можете перетаскивать шахматные фигуры по доске.

Чтобы построить это, вам нужно сначала создать приложение с одним представлением и получить несколько изображений. Один из моих любимых веб-сайтов для такого рода вещей — https://thenounproject.com, где они утверждают, что у них есть иконки для всего. Я нашел и скачал набор шахмат, сделанный [email protected] и пошел оттуда, это его шахматные фигуры, которые вы видите на изображении выше.

Я скопировал изображения в Assets.xcassets и создал простой цикл в моем viewDidLoad, чтобы создать доску и поместить в нее части. Код выглядит так.

var image2M: UIImageView!
var image2A:[UIImageView] = []
 
var sourceIndex: Int!
var objectIndex: Int!
let cpieces = [0:”wCastle”,1:”wKnight”,2:”wBishop”,3:”wQueen”,4:”wKing”,5:”wBishop”,6:”wKnight”,7:”wCastle”,8:”wPawn”,9:”wPawn”,10:”wPawn”,11:”wPawn”,12:”wPawn”,13:”wPawn”,14:”wPawn”,15:”wPawn”,48:”bPawn”,49:”bPawn”,50:”bPawn”,51:”bPawn”,52:”bPawn”,53:”bPawn”,54:”bPawn”,55:”bPawn”,56:”bCastle”,57:”bKnight”,58:”bBishop”,59:”bQueen”,60:”bKing”,61:”bBishop”,62:”bKnight”,63:”bCastle”]
 
var imageIndex = 0
let midX = self.view.bounds.midX — (8 * 64) / 2
let midY = self.view.bounds.midY — (8 * 64) / 2
for Xloop in 0..<8 {
  for Yloop in 0..<8 {
    let image2D = UIImageView(frame: CGRect(x: Int(midX + CGFloat(Xloop) * 64), y: Int(midY + CGFloat(Yloop) * 64), width: 64, height: 64))
    image2D.layer.borderColor = UIColor.black.cgColor
    image2D.layer.borderWidth = 1
    image2D.isUserInteractionEnabled = true
    image2D.tag = imageIndex
    if cpieces[imageIndex] != nil {
      image2D.image = UIImage(named: cpieces[imageIndex]!)
    }
 
    imageIndex = imageIndex + 1
    self.view.addSubview(image2D)
    image2A.append(image2D)
  }
}

Я хочу, чтобы доска находилась в центре экрана, отсюда и строки view.bounds, и я хотел создать доску как можно быстрее и проще, поэтому я просто добавляю к ней 64 UIImageViews с границами. Словарь хорошо помог мне расставить шахматные фигуры. Требования к массиву и тегу станут более очевидными по мере продвижения вперед.

Что касается интересной части, то если вы скопируете и вставите этот код в свой ViewController, у вас не будет ничего, кроме статической шахматной доски. Чтобы сделать его интерактивным, мне нужно было добавить в VC как UIDropInteractionDelegate, так и UIDragInteractionDelegate.

После этого вам нужно добавить эти четыре строки в цикл image2D, показанный выше.

let dragInteraction = UIDragInteraction(delegate: self)
image2D.addInteraction(dragInteraction)
let dropInteraction = UIDropInteraction(delegate: self)
image2D.addInteraction(dropInteraction)

И затем вы добавляете свои методы перетаскивания.

func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
  image2M = interaction.view as? UIImageView
  sourceIndex = image2M.tag
  let image = image2M.image
  let provider = NSItemProvider(object: image!)
  let item = UIDragItem(itemProvider: provider)
  item.localObject = image
  print(“sourceIndex \(sourceIndex)”)
  return [item]
}

Это захватывает выбранное изображение, а также квадрат, на котором оно находится прямо сейчас, с тегом для imageView, содержащим индекс UIImageArray, в котором он находится.

Нам также нужно добавить еще два метода для захвата действия перетаскивания.

func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
  session.loadObjects(ofClass: UIImage.self) { imageItems in
    let images = imageItems as! [UIImage]
    let dropLocation:CGPoint = session.location(in: self.view)
    for image2X in self.image2A {
      if (image2X.frame.contains(dropLocation) ) {
        image2X.image = images.first
        self.objectIndex = image2X.tag
        print(“objectIndex \(self.objectIndex)”)
        self.image2M.image = nil
      }
    }
  }
}

Это получает изображение, на которое вы перетащили, и dropLocation, на которое вам нужно его поместить. Затем он использует свой массив квадратов, чтобы найти ссылку на тот, на который вы поместили свое изображение, прежде чем поместить его туда, и снова отметить номер индекса изображения, который вы также переместили.

func dropInteraction(_ interaction: UIDropInteraction,
 sessionDidUpdate session: UIDropSession) -> UIDropProposal {
 return UIDropProposal(operation: .move)
 }

Что подводит нас к концу... если вы скопируете и вставите этот код в новый проект, вы должны получить очень простую шахматную партию. Посмотрите часть II, если вам понравился этот пост.