快速镶嵌机

在本系列文章的后续部分,我将继续研究新的拖放方法,我将另一个简单的游戏组合在一起,该游戏构建了一个空投文件的马赛克,使您有机会进行重新组合并将其重组为讨价还价。 [摇动iPad扰乱图像]。

为此,您需要先编辑info.plist,然后添加应用所需的代码以重新协调针对该图像的图像。

   UTExportedTypeDeclarations  


UTTypeConformsTo

public.data

UTTypeIdentifier
ch.cqd.mosaicMaker
UTTypeTagSpecification

public.filename-extension
mosaicMaker


这就是说,当您获得以.mosaicMaker结尾的文档时,您需要打开此应用程序。 当然,这意味着我需要更改要空投的jpg的扩展名,对不起,其中最纯粹的人不是。

添加的内容是,我需要将此代码放入应用程序委托中,以对传入的文件进行处理。是的,将扩展名更改回jpg。 显然,如果您将其发送给png,它将无法正常工作!

  func application(_ app:UIApplication,打开url:URL,选项:[UIApplicationOpenURLOptionsKey:Any] = [:])-> Bool { 
var destinationPath:URL!
让documentsDirectoryURL =试试! FileManager()。url(用于:.documentDirectory,位于:.userDomainMask中,适当用于:nil,创建:true)
如果url.pathExtension ==“ mosaicMaker” {
让documentsDirectoryURL =试试! FileManager()。url(用于:.documentDirectory,位于:.userDomainMask中,适当用于:nil,创建:true)
做{
destinationPath = documentsDirectoryURL.appendingPathComponent(“ mosaic.jpg”)
尝试FileManager.default.moveItem(at:url,to:destinationPath)
} {
打印(错误)
}
}
让nc = NotificationCenter.default
nc.post(name:Notification.Name(rawValue:” showImage”),
对象:无,userInfo:无)
返回真
}

除此之外,它还使用iOS标准通知中心来告诉ViewController它已加载了需要显示的图像。

在View Controller的viewDidLoad中,我们需要进行注册以接收通知,并告诉我们在收到通知时应如何处理; 在这种情况下,请运行方法showImage。

 让nc = NotificationCenter.default 
nc.addObserver(forName:Notification.Name(rawValue:” showImage”),
对象:无,队列:无,使用:self.showImage(notification:))

如果您正在阅读我写的其他文章,您需要重新整理显示图像中的一些代码,它将图像分成4×4的部分,绘制网格以固定它们,并使用拖放协议注册每个图像。 该代码中的几个要点。 首先,我们使用UIStackViews来管理布局,因此我们只需要给初始stackview提供X / Y约束,而不是让它们在UIStackView实现中管理布局。 也就是说,我们确实需要为图像提供高度和宽度限制,因为UIImageViews没有固有尺寸。

  func showImage(notification:通知){ 
让documentsDirectoryURL =试试! FileManager()。url(用于:.documentDirectory,位于:.userDomainMask中,适当用于:nil,创建:true)
让sourcePath = documentsDirectoryURL.appendingPathComponent(“ mosaic.jpg”)
让image2C = UIImage(contentsOfFile:sourcePath.path)
让image2R = splitImage(image2D:image2C!)
whiteWin = UIStackView()
whiteWin.axis = UILayoutConstraintAxis.vertical
whiteWin.distribution = UIStackViewDistribution.equalSpacing
whiteWin.alignment = UIStackViewAlignment.center
whiteWin.spacing = 8.0
self.view.addSubview(whiteWin)
var index2C = 0
for oLoop in stride(from:0,to:4,by:1){
让SV = UIStackView()
SV.axis = UILayoutConstraintAxis.horizo​​ntal
SV.distribution = UIStackViewDistribution.equalSpacing
SV.alignment = UIStackViewAlignment.center
SV.spacing = 8.0
whiteWin.addArrangedSubview(SV)
for _ in stride(从:0,到:4,通过:1){
让image2S = UIImageView()
image2S.translatesAutoresizingMaskIntoConstraints = false
image2S.widthAnchor.constraint(equalToConstant:128).isActive = true
image2S.heightAnchor.constraint(equalToConstant:128).isActive = true
image2S.image = image2R [index2C]
image2S.isUserInteractionEnabled = true
让dragInteraction = UIDragInteraction(delegate:self)
image2S.addInteraction(dragInteraction)
让dropInteraction = UIDropInteraction(代表:自我)
image2S.addInteraction(dropInteraction)
SV.addArrangedSubview(image2S)
image2S.tag =循环
image2A.append(image2S)
index2C + = 1
}
}
whiteWin.translatesAutoresizingMaskIntoConstraints = false
whiteWin.centerXAnchor.constraint(equalTo:self.view.centerXAnchor).isActive = true
whiteWin.centerYAnchor.constraint(等于:
self.view.centerYAnchor).isActive = true
}

同时,这里的分割图像方法也需要定义,其代码如下所示。

  func splitImage(image2D:UIImage)-> [UIImage] { 
var imgImages:[UIImage] = []
让imgWH = image2D.size.width / 4
让imgHT = image2D.size.height / 4
让imgWS = image2D.size.width / 4
让imgHS = image2D.size.height / 4
  //由于我们有4个部分,因此需要考虑精度误差并将总宽度减少4 
  for imgCH in stride(from:0,to:Int(image2D.size.height)— 4,作者:Int(imgHS)){ 
for imgCW in stride(from:0,to:Int(image2D.size.width)— 4,作者:Int(imgWS)){
 让imgRect = CGRect(x:imgCW,y:imgCH,宽度:Int(imgWH),高度:Int(imgHT)) 
让imgChop = image2D.cgImage?.cropping(to:imgRect)
让img2D = UIImage(cgImage:imgChop!)
imgImages.append(img2D)
}
}
返回imgImages
}

这里也有一个导入警告,如果图像没有分成四个相等的部分,则精度错误将导致此循环失败。 我们通过将图像的大小减小4来捏造这一点。我不知道它是否仍然有效,您可以对其进行测试🙂

只需再执行几行代码即可完成操作,请原谅。

  func dragInteraction(_交互:UIDragInteraction,itemsForBeginning会话:UIDragSession)-> [UIDragItem] { 
image2M = interact.view为? UIImageView
sourceIndex = image2M.tag
让image = image2M.image
让provider = NSItemProvider(对象:图像!)
让item = UIDragItem(itemProvider:提供程序)
item.localObject =图片
归还物品]
}
  func dropInteraction(_交互:UIDropInteraction,performDrop会话:UIDropSession){ 
session.loadObjects(ofClass:UIImage.self){imageItems in
让images = imageItems作为! [UIImage]
让dropLocation:CGPoint = session.location(in:self.view)
用于self.image2A中的image2X {
让frame = self.view.convert(image2X.frame,from:image2X.superview)
如果(frame.contains(dropLocation)){
self.objectIndex = image2X.tag
让image2S = image2X.image
image2X.image = images.first
self.image2M.image = image2S
}
}
}
}
  func dropInteraction(_交互:UIDropInteraction, 
  sessionDidUpdate会话:UIDropSession)-> UIDropProposal { 
 返回UIDropProposal(操作:.move) 
}

拖放方法,显然,您需要同时将UIDrag和UIDrop委托添加到类中,以便调用它们。 该代码中的重要细节; 返回到拖动视图的放置视图的坐标来自主要的self.view坐标系统,但是我们的图像数组包含来自stackview放置位置的坐标; 为了缩小差距,我们还需要在寻找匹配项之前将imageViews的坐标转换为主要的self.view。

而且,有了几乎所有东西,唯一丢失的部分就是当您摇动iPad时对图像进行加扰的代码,如下所示。

 覆盖func motionEnded(_ motion:UIEventSubtype,并带有事件:UIEvent?){ 
 如果运动== .motionShake { 
DispatchQueue.main.async {
var image2B:[UIImage] = []
用于self.image2A中的image2S {
image2B.append(image2S.image!)
}
var image2C = image2B.shuffled()
用于self.image2A中的image2S {
image2S.image = image2C.popLast()
}
}
}
}

看起来也使用GameKit方法并且可以作为Array扩展实现的用于重排图像的代码。

 扩展数组{ 
func shuffled(使用来源:GKRandomSource)-> [Element] {
 返回(本身作为NSArray).shuffled(使用:源)为!  [元件] 
}
  func shuffled()-> [Element] { 
返回(本身作为NSArray).shuffled()为! [元件]
}
}

告诉我你的想法? 这一切有意义吗? 最后的评论是,您只能使用此应用一次🙂保存jpg的第二次失败,我将其留给读者修复代码!

信用:需要感谢Shoo Rayner https://www.youtube.com/watch?v=McyImAXhUDY&lc=z22ry5phfyv5xrcn2acdp431k45z11pkghi1tcmhrodw03c010c&feature=em-comments谁是我在初始图像中用作演示的BB8; 并确实以《星球大战》打造了BB8机器人。