SD not setting Image pulled from Firebase Storage - swift

I am following Google's guide for getting an image from the storage and then placing it into an imageView using "FirebaseStorageUI", which seems to use SDWebImage.
I have the problem that the image simply is not set. There are no errors in the console. My code:
#IBOutlet weak var imageView: UIImageView!
var ref = FIRDatabase.database().reference()
var storageRef = FIRStorage.storage().reference()
override func viewWillAppear(_ animated: Bool) {
self.getHouseID(){ (houseName) -> () in
if houseName.characters.count > 0 {
self.houseIDLabel.text = houseName // does work correctly
let photoRef = self.storageRef.child("\(houseName)/\("housePhoto.jpg")")
self.housePhotoImageView.sd_setImage(with: photoRef) // not working
} else {
print("error while setting image and house name label")
}
}
}
My Storage looks like this:
The label gets correctly set with the houseName, which is also used in the storage path to retrieve the image. Anything I have missed here?

1. I think the problem is that your awesomehouse/ has a slash in the end.
Try to check which child() your are creating: awesomehouse or awesomehouse/
2. The second possible problem is that you are trying to fetch "housePhoto.jpg" instead of stored housePhoto.
So, it should be:
let photoRef = self.storageRef.child("awesomehouse/").child("housePhoto")
self.housePhotoImageView.sd_setImage(with: photoRef) // should work now
Or it better to save photo to storage with extension ".jpg", then it would be:
let photoRef = self.storageRef.child("awesomehouse/").child("housePhoto.jpg")
self.housePhotoImageView.sd_setImage(with: photoRef) // should work now
Try both. I think it will solve your problem.
Hope it helps

My first guess would be that you are not setting this on the main queue.
Try this:
DispatchQueue.main.async {
self.housePhotoImageView.sd_setImage(with: photoRef)
}
I don't know if it matters that your image file does not have a file extension, that might also be worth trying. Hope this helps

Related

Swift - Getting UIImages from Camera (AVCaptureSession)

Intro and background:
I have been working on a project for sometime that lets the user do some custom manipulations from their camera (a live feed)
At the moment, I start the capture session in the following way:
var session: AVCaptureSession?
var stillImageOutput: AVCaptureStillImageOutput?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
videoPreviewLayer!.frame = CameraView.bounds
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
session = AVCaptureSession()
session!.sessionPreset = AVCaptureSessionPresetPhoto
let backCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
var error: NSError?
var input: AVCaptureDeviceInput!
do {
input = try AVCaptureDeviceInput(device: backCamera)
} catch let error1 as NSError {
error = error1
input = nil
}
if error == nil && session!.canAddInput(input) {
session!.addInput(input)
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if session!.canAddOutput(stillImageOutput) {
session!.addOutput(stillImageOutput)
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
videoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
videoPreviewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
CameraView.layer.addSublayer(videoPreviewLayer!)
session!.startRunning()
}
}
}
where CameraView is the UIView of my viewcontroller. I now have a function called: singleTapped() that I want to get every frame of the capture, process it, then put into the CameraView frame (Perhaps I should be using a UIImageView instead?)...
Research:
I have looked here and here, as well as many others for getting the frames of the camera, yet these don't necessarily conclude where I need. What's interesting is in the first link I provided: In their answer they have:
self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.stillImageOutput.connectionWithMediaType(AVMediaTypeVideo)) { (buffer:CMSampleBuffer!, error:NSError!) -> Void in
var image = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
var data_image = UIImage(data: image) //THEY EXTRACTED A UIIMAGE HERE
self.imageView.image = data_image
}
which does indeed get a UIImage from the camera, but is this a viable method for 30fps?
Rational and Constraints:
The reason for why I need a UIImage is because I am utilizing a library someone else wrote for transforming a UIImage in a custom way quickly. I want to present this transformation to the user "live".
In conclusion
Please let me know if I am missing something, or if I should reword something. As said above this is my first post, so I am not quite strong with SO nuances. Thanks, and cheers
You should maybe try reconsider using AVCaptureSession. For what you are doing (I assume) you should try using OpenCV. Its a great utility for image manipulations, especially if you are doing so at 30/60fps* (The actual frame rate after processing might, and I guarantee will, be less). Depending on what this manipulation is you have been given, you can easily port that over into XCode using bridging headers or converting everything entirely to C++ for use with OpenCV.
With OpenCV you can call the camera from built-in functions and that can save you lots of processing time and therefore runtime. For example, take a look at this.
I have used OpenCV for similar situations to which you just described, and I think you could benefit. Swift is nice, but sometimes handling certain things are better through other means...

Show Image from URL in detailView after selection in tableView

I have a tableView which display a list of traffic-cameras parsed from a XML file. When I select a cell, it sends the ImageURL, Roadname, Coordinates etc. via the prepareForSegue method.
In my detailviewcontroller I declare the incoming values as the following:
var selectedFeedURL = String()
var selectedFeedRoadname = String()
var selectedFeedLongitude = String()
var selectedFeedLatitude = String()
I have no problem printing all the values into the log or set it as labels. The problem occurs when I try to load the selectedFeedURL (which is the URL to the image, i.e: http://webkamera.vegvesen.no/kamera?id=559847) and set it to my imageView..
In my viewDidLoad, I have the following code, which should download the image and set it to my imageView named cameraImageView.
if let url = NSURL(string:"\(selectedFeedURL)") {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}
My imageView stays empty and I doesn't get any errors or complains in the debug area. If I print out the selectedFeedURL, the link is there.
The weird part is that if I change
NSURL(string:"\(selectedFeedURL)")
to
NSURL(string:"http://webkamera.vegvesen.no/kamera?id=559847")
Basically changing the variable to a camera URL, it works perfectly.
Soo... any suggestions on what the problem might be?
Much appreciated :)
If there are white spaces and newline characters at the start and end of your URL string, it won't work.
Try:
selectedFeedURL = selectedFeedURL.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
if let url = NSURL(string: selectedFeedURL) {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}

Swift - Using value from UISlider IBAction in another function

This is a super basic question that is troubling me.
I have a UIslider IBAction that is generating a Double (var = rounded). I want to use this double in viewDidLoad. but getting the error "Use of unresolved identifier 'rounded'"
#IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Double(sender.value)
var rounded = Double(round(100*currentValue)/100)
label.text = "\(rounded)"
}
override func viewDidLoad() {
super.viewDidLoad()
let fileURL = NSBundle.mainBundle().URLForResource("puppy", withExtension: "jpg")
let beginImage = CIImage(contentsOfURL: fileURL)
let filter = CIFilter(name: "CISepiaTone")
filter.setValue(beginImage, forKey: kCIInputImageKey)
filter.setValue(rounded, forKey: kCIInputIntensityKey)
let newImage = UIImage(CIImage: filter.outputImage)
self.imageView.image = newImage
}
filter.setValue(rounded, forKey: kCIInputIntensityKey) is where i am getting the error. I want to use the 'rounded' variable from the slider function here.
Any help in using one variable from one function in another function would be very much appreciated. I have ran into this a couple times without success. So once you all help me out here, it should fix my other issues as well.
Thanks
Declare an instance variable at the beginning of the class – outside any method – with the default value of the UISlider
var rounded : Double = <defaultValueOfTheSlider>
delete the keyword var before rounded in sliderValueChanged()
A few concepts that will help you out.
The issue you are having is that you are creating an instance inside a function and it is lost when the function returns. The reason for this is that the functions data is created on the stack, the stack is temporary memory your app's process uses.
To access the variable throughout the class you can declare it at the top of your class. This will then be allocated to the heap so that it's available for later access until removed from the heap(deallocated).

Displaying images with action in swift?

I'm a kind new to Xcode/swift, I am trying to build a game where 5 pics need to selected randomly, my code looks something like that :
var options = ["1.png","2.png","3.png","4.png","4.png"]
#IBAction func option1(sender: AnyObject) {
var randomNumber = Int(arc4random_uniform(5))
**iphoneChoise.image(options[randomNumber])** /*This line is not correct*/
}
Please help!
Make an #IBOutlet for your image view.
Then, assuming your images are saved in Images.xcassets:
#IBAction func option1(sender:AnyObject){
var randomNumber = Int(arc4random_uniform(5))
yourImageViewIBOutlet.image = UIImage(named: options[randomNumber])
}
You should try something like :
yourImageView.image = UIImage(named: "imageName")
In you case, it should like like this :
var options = ["1.png","2.png","3.png","4.png","4.png"]
#IBAction func option1(sender: AnyObject) {
var randomNumber = Int(arc4random_uniform(5))
iphoneChoise.image = UIImage(named: options[randomNumber])
}
Make sure the images are within the project (inside the Images.xcassets for example).
If it didn't helped, please provide more information : "what" is _iphoneChoise_ and what error are you facing.
You can simplify the code for your random image by using the following code:
var randomImageGeneratorNumber = acr4random_uniform(5) + 1
YourImageView.image = UIImage(named: "\(randomImageGeneratorNumber).png")
This is called "String Interpolation"
Hope this will help you by making your code a bit shorter.

UIImageView is NIL

I have a default image in viewItem to make sure that it is working, it shows on the detail view of the splitview.
#IBOutlet weak var ImageView: UIImageView!
var imageCache = [String: UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.configureView()
}
func configureView() {
if let detail: AnyObject = self.detailItem {
if let label = self.detailDescriptionLabel {
let dict = detail as [String: String]
label.text = ""
let s = dict["result"]
let vr = NString(string: s!)
let vrd = vr.doubleValue
let value = ceil(vrd*20)
let valueString = String(format: "%.0f", value)
vresult.text = "\(valueString)%"
getPic(dict) // <---- trouble maker
fitem.hidden = false
ritem.hidden = false
}
} else {
navigationController?.popViewControllerAnimated(true)
}
}
func getPic(item: [String: String]) {
var chachedImage = self.imageCache[item["image"]!]
println(item["image"]) // <-- prints out the url
if cachedImage == nil {
var imgUrl = NSURL(string: item["image"]!)
let request: NSURLRequest = NSURLRequest(URL: imgUrl!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {( reponse: NSURLResponse!, data: NSData!, error; NSError!) -> Void in
if error == nil {
cachedImage = UIImage(data: data)
println("got here no problem") // <-- prints out
self.imageCache[item["image"]!] = cachedImage
println(self.imageCache) // <-- prints reference OK
dispatch_async(dispatch_get_main_queue(), {
self.ImageView.image = cachedImage // <---- offender
})
} else {
println("Error: \(error.localizedDescription)")
}
})
} else {
dispatch_async(dispatch_get_main_queue(), {
self.ImageView.image = cachedImage
})
}
}
ImageView is coming up nil every time.
fatal error: unexpectedly found nil while unwrapping an Optional value
but the default image shows. I've moved this out of the dispatch and even tried setting it straight from the viewDidLoad() always errors. It used to be a UIWebView and worked perfectly except that it would not cache anything. Since loading these images is a lot of work, I thought caching would be good, I've got caching working for thumbnails in the MASTER view.
It may be because of how your instaciating your viewcontroller.
let vc = MyViewController()
Something like this wont work. You're creating the VC without actually giving the storyboard a chance to link the IBOutlets. Instead use
storyboard.instantiateViewControllerWithIdentifier(identifier: String)
You may need to get reference to the storyboard using
let storyboard = UIStoryboard(name: name, bundle: NSBundle.mainBundle())
Hope this helps :)
Changing your variable name shouldn't make any difference except for readibility/maintainability unless there's a namespace conflict (good to understand why/where that might be happening). Also I was wondering - you made the IBOutlet'ed varable weak. When the last remaining strong ref to the object goes away, the weak references to the object are set nil by the runtime/garbage collector automatically. (Look up that section of the Swift documentation if you're not solid about it).
Maybe you should check your classes and controllers by adding deinit { println(,"function name deallocated' }. Between your use of weak and improved behavior seen when you change the variable name, it seems like there might be some weird (buggy) interactions going on in your app itself.
Well silly me. I've been working on this for a few days, I got the great idea to try and change the name, and it worked. I tried changing it back and it broke, apparently you can't use ImageView as a variable!
In my case was because I was using a nib and didn't register it.
Once I did registered it, it worked
My case Was Different I used
awakeFromNib()
instead of
viewDidLoad()
.