我正在尝试创建一个应用程序,该应用程序包含一个集合视图,其中拖动了图像。
我在一个双显示屏中打开谷歌图像,搜索“海豹”,并将海豹的第一张图像拖到我的应用程序的视图控制器上。我的应用程序应该保存图像的url。集合视图中的每个单元格都会从保存的url中获得一个url。设置url后,单元格从url中检索图像并将图像放置在其内部。
问题是错误的网址被带走了。可以将url转换成数据,但是不能将数据转换成UIImage。从拖放中保存的url不是图像的url,它似乎是google搜索或其他内容的url。
我需要能够保存图像的正确url,以便ImageCell可以从url加载图像。
当我在浏览器中输入网址时,我看到了这样一个页面。
ImageView控制器
import UIKit
class ImageViewController: UIViewController{
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
var gallery = [URL]()
}
extension ImageViewController: UICollectionViewDelegate, UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return gallery.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as! ImageCell
cell.url = gallery[indexPath.item]
return cell
}
}
extension ImageViewController: UICollectionViewDropDelegate{
func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
return session.canLoadObjects(ofClass: NSURL.self) && session.canLoadObjects(ofClass: UIImage.self)
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
return UICollectionViewDropProposal(operation: .copy)
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
// Get the destion index path, if there's none set, just insert at the beginning
let destinationIndexPath = coordinator.destinationIndexPath ?? IndexPath(item: 0, section: 0)
// Process all items being dragged
for item in coordinator.items {
// External drops must provide url and an image that we'll use to get an aspect-ratio
var url: URL?
// Get the URL
item.dragItem.itemProvider.loadObject(ofClass: NSURL.self) { [weak self] (provider, error) in
url = provider as? URL //Check that url is valid
// If both url and ratio were provided, perform the actual drop
if url != nil{
DispatchQueue.main.async {
collectionView.performBatchUpdates({
// Update model
self?.gallery.insert(url!, at: destinationIndexPath.item)
// Update view
collectionView.insertItems(at: [destinationIndexPath])
// Animates the item to the specified index path in the collection view.
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
})
}
}
}
}
}
}
图像单元
class ImageCell: UICollectionViewCell{
var url: URL?{
didSet{
self.fetchImage(withURL: url!)
}
}
@IBOutlet var imageView: UIImageView!
private func fetchImage(withURL url: URL) {
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let data = try? Data(contentsOf: url) else {
return
}
guard let image = UIImage(data: data) else {
print("Couldn't convert data to UIImage")
print("The url is")
print(url)
return
}
// If by the time the async. fetch finishes, the imageURL is still the same, update the UI (in the main queue)
if self?.url == url {
DispatchQueue.main.async {
self?.imageView.image = image
}
}
}
}
}
开源代码库
这是我在 github 上的项目
要从从谷歌图像拖放提供的url中提取图像url,可以将这些扩展添加到url中。然后,在保存url的变量(url
)上,可以使用url!访问图像url!。imageURL
而不仅仅是url代码>
extension URL {
var imageURL: URL {
if let url = UIImage.urlToStoreLocallyAsJPEG(named: self.path) {
// this was created using UIImage.storeLocallyAsJPEG
return url
} else {
// check to see if there is an embedded imgurl reference
for query in query?.components(separatedBy: "&") ?? [] {
let queryComponents = query.components(separatedBy: "=")
if queryComponents.count == 2 {
if queryComponents[0] == "imgurl", let url = URL(string: queryComponents[1].removingPercentEncoding ?? "") {
return url
}
}
}
return self.baseURL ?? self
}
}
}
extension UIImage
{
private static let localImagesDirectory = "UIImage.storeLocallyAsJPEG"
static func urlToStoreLocallyAsJPEG(named: String) -> URL? {
var name = named
let pathComponents = named.components(separatedBy: "/")
if pathComponents.count > 1 {
if pathComponents[pathComponents.count-2] == localImagesDirectory {
name = pathComponents.last!
} else {
return nil
}
}
if var url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
url = url.appendingPathComponent(localImagesDirectory)
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
url = url.appendingPathComponent(name)
if url.pathExtension != "jpg" {
url = url.appendingPathExtension("jpg")
}
return url
} catch let error {
print("UIImage.urlToStoreLocallyAsJPEG \(error)")
}
}
return nil
}
func storeLocallyAsJPEG(named name: String) -> URL? {
if let imageData = self.jpegData(compressionQuality: 1.0) {
if let url = UIImage.urlToStoreLocallyAsJPEG(named: name) {
do {
try imageData.write(to: url)
return url
} catch let error {
print("UIImage.storeLocallyAsJPEG \(error)")
}
}
}
return nil
}
}