快速镶嵌机
在本系列文章的后续部分,我将继续研究新的拖放方法,我将另一个简单的游戏组合在一起,该游戏构建了一个空投文件的马赛克,使您有机会进行重新组合并将其重组为讨价还价。 [摇动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.horizontal
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机器人。