Reputation: 67
I want to add ARReferenceImages from a server. For this I get an array with the URL's to the images. T tried with the following function, that iterates the url's and adds the new created ARImages to the set. But it does not work.
func addReferences(media: NSArray){
var customReferenceSet = Set<ARReferenceImage>()
for medium in media{
let type = (medium as AnyObject).value(forKey: "type");
let t = type as! String
let reference = (medium as AnyObject).value(forKey: "reference");
let ref = reference as! String
let ide = (medium as AnyObject).value(forKey: "id");
let id = ide as! String
let url = URL(string: ref)
let session = URLSession(configuration: .default)
let downloadPicTask = session.dataTask(with: url!) { (data, response, error) in
if let e = error {
print("Error downloading picture: \(e)")
} else {
if let res = response as? HTTPURLResponse {
print("Downloaded picture with response code \(res.statusCode)")
if let imageData = data {
let image = UIImage(data: imageData)!
let imageToCIImage = CIImage(image: image)
let cgImage = self.convertCIImageToCGImage(inputImage: imageToCIImage!)
let arImage = ARReferenceImage(cgImage!, orientation: CGImagePropertyOrientation.up, physicalWidth: 0.2)
arImage.name = id
customReferenceSet.insert(arImage)
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
self.configuration = ARWorldTrackingConfiguration()
self.configuration?.detectionImages = customReferenceSet
sceneView.session.run(configuration!)
}
Sometimes, but not everytime, I get the following output:
[boringssl_session_read] SSL_ERROR_ZERO_RETURN(6): operation failed because the connection was cleanly shut down with a close_notify alert
Some ideas?
Upvotes: 1
Views: 1282
Reputation: 54775
The issue is that you set detectionImages
before the async network requests could actually fetch the images, meaning that you actually assign the empty set to detectionImages
.
You need to make sure that you only set detectionImages
once all images were fetched from the server, which you can achieve by using a DispatchGroup
.
func addReferences(media: NSArray){
var customReferenceSet = Set<ARReferenceImage>()
let imageFetchingGroup = DispatchGroup()
for medium in media {
let type = (medium as AnyObject).value(forKey: "type");
let t = type as! String
let reference = (medium as AnyObject).value(forKey: "reference");
let ref = reference as! String
let ide = (medium as AnyObject).value(forKey: "id");
let id = ide as! String
let url = URL(string: ref)
let session = URLSession(configuration: .default)
imageFetchingGroup.enter()
let downloadPicTask = session.dataTask(with: url!) { (data, response, error) in
if let e = error {
print("Error downloading picture: \(e)")
imageFetchingGroup.leave()
} else {
if let res = response as? HTTPURLResponse {
print("Downloaded picture with response code \(res.statusCode)")
if let imageData = data {
let image = UIImage(data: imageData)!
let arImage = ARReferenceImage(image.cgImage!, orientation: CGImagePropertyOrientation.up, physicalWidth: 0.2)
arImage.name = id
customReferenceSet.insert(arImage)
imageFetchingGroup.leave()
} else {
print("Couldn't get image: Image is nil")
imageFetchingGroup.leave()
}
} else {
print("Couldn't get response code for some reason")
imageFetchingGroup.leave()
}
}
}
downloadPicTask.resume()
}
self.configuration = ARWorldTrackingConfiguration()
imageFetchingGroup.notify(queue: .main) {
self.configuration?.detectionImages = customReferenceSet
sceneView.session.run(configuration!)
}
}
You also shouldn't use NSArray
in Swift and especially shouldn't cast types with known properties to AnyObject
just to the dynamically retrieve their properties using value(forKey:)
with static keys. Simply use Array
with the concrete type and access the properties using the dot syntax.
There's also no need for the custom conversion from UIImage
to CIImage
and then to CGImage
, UIImage
has a built in property, cgImage
that you can use for the conversion.
Upvotes: 2