How to get filename last photo in Swift 2.0 iOS9? - image

I want to get file_name (example = IMG_xxxx.jpg)
func lastphoto() {
var fetchOptions: PHFetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
var fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
if (fetchResult.lastObject != nil) {
var lastAsset: PHAsset = fetchResult.lastObject as! PHAsset
let options:PHImageRequestOptions = PHImageRequestOptions()
options.version = PHImageRequestOptionsVersion.Current
PHImageManager.defaultManager().requestImageForAsset(lastAsset,
targetSize: self.imageView.bounds.size,
contentMode: PHImageContentMode.AspectFill,
options: PHImageRequestOptions(),
resultHandler: { (result, info) -> Void in
self.imageView.image = result
let manager = PHImageManager.defaultManager()
let assets = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)
})
}
}

As of iOS 9.0, you can get the original file name using the following:
var filename: String?
if #available(iOS 9.0, *) {
let resources = PHAssetResource.assetResourcesForAsset(lastAsset)
if let resource = resources.first {
filename = resource.originalFilename
}
}
If you're supporting pre-iOS 9.0 versions, you can also try using an undocumented workaround that still works as of iOS 9.1:
filename = lastAsset.valueForKey("filename") as? String

Related

Not Executing Function at The Right Time, But Executed After Completion Block

Need help in figuring out why my function is not executing when I thought it should but it executed after the completion block in the code. I am fairly new to Xcode so please excuse me if things sound confusing here. Below is my code.
class ImageDownloader{
typealias completionHandler = (Result<Set<ARReferenceImage>, Error>) -> ()
typealias ImageData = (image: UIImage, orientation: CGImagePropertyOrientation, physicalWidth: CGFloat, name: String)
static let URLDic = [ReferenceImagePayload]()
class func getDocumentData(completion:#escaping ([ReferenceImagePayload]) -> ()) {
var documentCollection: [ReferenceImagePayload] = []
db.collection("Users").getDocuments {(snapshot, error) in
if error == nil && snapshot != nil {
var index = 0
for document in snapshot!.documents {
let loadData = document.data()
index += 1
if loadData["Target URL"] != nil {
let url = loadData["Target URL"]
let urlString = URL(string: "\(String(describing: url ?? ""))")
let urlName = loadData["Target Image"]
documentCollection.append(ReferenceImagePayload(name: urlName as! String, url: urlString!))
if snapshot!.documents.count == index {
// After finished, send back the loaded data
completion(documentCollection)
}
}
}
}
}
}
static var receivedImageData = [ImageData]()
class func downloadImagesFromPaths(_ completion: #escaping completionHandler) {
// THE LINE BELOW WHERE I CALL THE FUNCTION IS NOT EXECUTED WHEN THIS CLASS IS INITIALLY CALLED. BUT AS THE CODE RUNS, THIS LINE BELOW IS EXECUTED AFTER THE COMPLETIONOPERATION = BLOCKOPERATION IS COMPLETED.
let loadedDataDic: () = getDocumentData { (URLDic) in
print(URLDic.self, "Got it")
}
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 6
let completionOperation = BlockOperation {
OperationQueue.main.addOperation({
completion(.success(referenceImageFrom(receivedImageData)))
// LINE "let loadedDataDic: () = getDocumentData" ONLY GOT EXECUTED AT THIS POINT
})
}
URLDic.forEach { (loadData) in
let urlstring = loadData.url
let operation = BlockOperation(block: {
do{
let imageData = try Data(contentsOf: loadData.url)
print(imageData, "Image Data")
if let image = UIImage(data: imageData){
receivedImageData.append(ImageData(image, .up, 0.1, loadData.name))
}
}catch{
completion(.failure(error))
}
})
completionOperation.addDependency(operation)
}
operationQueue.addOperations(completionOperation.dependencies, waitUntilFinished: false)
operationQueue.addOperation(completionOperation)
}
}

call child data from firebase

Good evening,
I am trying to call data to post onto a card very similar to tinder. When I run my code, everything works and I see the print statement in the console. However the card view shows a default image with default text.
I was wondering if anyone has encountered this issue and could possibly help explain what I am doing wrong.
fileprivate func fetchUsersFromDatabase() {
Database.database().reference().child("JobPost").observeSingleEvent(of: .value, with: {(Snapshot) in
if let eachDict = Snapshot.value as? NSDictionary{
for each in eachDict{
//I think the issue is caused by the let post = poster
let post = Poster(dictionary: Snapshot.value as! [String : Any])
self.cardViewModels.append(post.toCardViewModel())
print(each.value )
}
}
self.setupDummyCards()
}, withCancel: {(Err) in
})
}
// the struct is in an extension file.
struct Poster: ProducesCardViewModel{
var jobName : String?
var price: Int?
var postName: String?
var ImageUrl1: String?
var uid: String?
init(dictionary: [String: Any]) {
self.price = dictionary["cost"] as? Int
self.jobName = dictionary["category"] as? String
self.postName = dictionary["description"] as? String ?? ""
self.ImageUrl1 = dictionary["JobImageUrl"] as? String ?? ""
self.uid = dictionary["fromId"] as? String ?? ""
}
func toCardViewModel() -> CardViewModel {
let attributedText = NSMutableAttributedString(string: jobName ?? "", attributes: [.font: UIFont.systemFont(ofSize: 32, weight: .heavy)])
let priceString = price != nil ? "\(price!)" : "N\\A"
attributedText.append(NSAttributedString(string: " \(priceString)", attributes: [.font: UIFont.systemFont(ofSize: 24, weight: .regular)]))
let jobString = jobName != nil ? jobName! : "Not available"
attributedText.append(NSAttributedString(string: "\n\(jobString)", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .regular)]))
return CardViewModel(imageNames: [ImageUrl1 ?? "" ], attributedString: attributedText, textAlignment: .left)
}
}
Example
// toCardViewModel
import UIKit
protocol ProducesCardViewModel {
func toCardViewModel() -> CardViewModel
}
class CardViewModel {
let JobimageName: [String]
let attributedString: NSAttributedString
let textAlignment: NSTextAlignment
init(imageNames: [String], attributedString: NSAttributedString, textAlignment: NSTextAlignment) {
self.JobimageName = imageNames
self.attributedString = attributedString
self.textAlignment = textAlignment
}
fileprivate var imageIndex = 0 {
didSet {
let imageName = JobimageName[imageIndex]
let image = UIImage(named: imageName)
imageIndexObserver?(imageIndex, image)
}
}
var imageIndexObserver: ((Int, UIImage?) -> ())?
func advanceToNextPhoto() {
imageIndex = min(imageIndex + 1, JobimageName.count - 1)
}
func goToPreviousPhoto() {
imageIndex = max(0, imageIndex - 1)
}
}
Thank you in advance!
// P.S I previously posted this question without lack of sufficient detail. I decided to just re post it with the quality material. I really appreciate your time.
I have figured out an answer and it was quite obvious to me. I noticed that
print(each.value )
would print the value, so I just substituted
let post = Poster(dictionary: Snapshot.value as! [String : Any])
to
let post = Poster(dictionary: each.value as! [String : Any])
and everything started to work just fine!

iOS 9(Swift 2.0): cannot invoke 'dataTaskwithURL' with an argument list of type '(NSURL, (_, _,_)throws -> Void)'

My app works perfectly fine with iOS 8 but yesterday I upgraded to iOS 9 and Xcode 7 then my app crashes. The error message is cannot invoke 'dataTaskwithURL' with an argument list of type '(NSURL, (_, ,)throws -> Void)'. I googled it and found a similar question here but the solution didn't really work (the solution was to add the do/catch blocks around the code). Can anyone help me with mine problem? Thank you!!!
Here's my code
import UIKit
import Foundation
import CoreLocation
class GoogleDataProvider {
let apiKey = "AIzaSyCQo-clIkek87N99RVh2lmFX9Mu9QPhAtA"
let serverKey = "AIzaSyBzmv7wPFcPAe1ucy5o6dqaXnda9i9MqjE"
var photoCache = [String:UIImage]()
var placesTask = NSURLSessionDataTask()
var session: NSURLSession {
return NSURLSession.sharedSession()
}
func fetchPlacesNearCoordinate(coordinate: CLLocationCoordinate2D, radius:Double, types:[String],keyword:String, completion: (([GooglePlace]) -> Void)) -> ()
{
var urlString = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=\(serverKey)&location=\(coordinate.latitude),\(coordinate.longitude)&radius=\(radius)&keyword=\(keyword)&rankby=prominence&sensor=true"
let typesString = types.count > 0 ? types.joinWithSeparator("|") : "food"
urlString += "&types=\(typesString)"
urlString = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
if placesTask.taskIdentifier > 0 && placesTask.state == .Running {
placesTask.cancel()
}
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
do{
//******************Here's the line that displays error
placesTask = session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var placesArray = [GooglePlace]()
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? NSDictionary {
if let results = json["results"] as? NSArray {
for rawPlace:AnyObject in results {
let place = GooglePlace(dictionary: rawPlace as! NSDictionary, acceptedTypes: types)
placesArray.append(place)
if let reference = place.photoReference {
self.fetchPhotoFromReference(reference) { image in
place.photo = image
}
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
completion(placesArray)
}
}
}catch{
}
placesTask.resume()
}
func fetchDirectionsFrom(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D, completion: ((String?) -> Void)) -> ()
{
let urlString = "https://maps.googleapis.com/maps/api/directions/json?key=\(serverKey)&origin=\(from.latitude),\(from.longitude)&destination=\(to.latitude),\(to.longitude)&mode=walking"
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
do{
//******************************Here too ****************************
session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var encodedRoute: String?
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? [String:AnyObject] {
if let routes = json["routes"] as AnyObject? as? [AnyObject] {
if let route = routes.first as? [String : AnyObject] {
if let polyline = route["overview_polyline"] as AnyObject? as? [String : String] {
if let points = polyline["points"] as AnyObject? as? String {
encodedRoute = points
}
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
completion(encodedRoute)
}
}.resume()
}catch{
}
}
}
Sorry this is my first time posting the code style is a little bit confusing sorry about the indentation mess :)
Thanks again!!!
dataTaskWithURL:completionHandler: does not throw error.
Put do and catch inside dataTaskWithURL method.
for example:
session.dataTaskWithURL(NSURL(string: urlString)!) {
(data, response, error) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
var encodedRoute: String?
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? [String:AnyObject] {
if let routes = json["routes"] as AnyObject? as? [AnyObject] {
if let route = routes.first as? [String : AnyObject] {
if let polyline = route["overview_polyline"] as AnyObject? as? [String : String] {
if let points = polyline["points"] as AnyObject? as? String {
encodedRoute = points
}
}
}
}
}
} catch {
}
dispatch_async(dispatch_get_main_queue()) {
completion(encodedRoute)
}
}.resume()

Swift 2.0: Could not find overload. Need Explanation

I have the following code in my program.
var detailItem: RSSItem? {
didSet {
self.configureView()
}
}
func configureView() {
if let item: RSSItem = self.detailItem
{
if let webView = self.itemWebView
{
if let templateURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("template", ofType: "html")!)?
{
if var template = NSString(contentsOfURL: templateURL, encoding: NSUTF8StringEncoding)?
{
if let title = item.title
{
template = template.stringByReplacingOccurrencesOfString("###TITLE###", withString: title)
}
if let content = item.content
{
template = template.stringByReplacingOccurrencesOfString("###CONTENT###", withString: content)
}
else if let description = item.itemDescription
{
template = template.stringByReplacingOccurrencesOfString("###CONTENT###", withString: description)
}
if let date = item.pubDate
{
var formatter = NSDateFormatter()
formatter.dateFormat = "MMM dd, yyyy"
template = template.stringByReplacingOccurrencesOfString("###DATE###", withString: formatter.stringFromDate(date))
}
if let author = item.author
{
template = template.stringByReplacingOccurrencesOfString("###AUTHOR###", withString: author)
}
webView.loadHTMLString(template, baseURL: nil)
}
}
else
{
if let content = item.content
{
webView.loadHTMLString(content, baseURL: nil)
}
else if let description = item.itemDescription
{
webView.loadHTMLString(description, baseURL: nil)
}
}
}
}
}
On the line:
if let templateURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("template", ofType: "html")!)?
I get the following error:
-Could not find an overload for 'pathForResource' that accepts the supplied arguments
Can someone explain this error to me and maybe suggest a solution. I have been reading through various searches on Google but can't quite seem to get what I need.
Thanks in advance.
NSURL(fileURLWithPath:) is now return a NSURL so just don't use if let here.
#available(iOS 2.0, *)
init(fileURLWithPath path: String, isDirectory isDir: Bool)
init(fileURLWithPath path: String) // Better to use initFileURLWithPath:isDirectory: if you know if the path is a directory vs non-directory, as it saves an i/o.
#available(iOS 2.0, *)
class func fileURLWithPath(path: String, isDirectory isDir: Bool) -> NSURL
class func fileURLWithPath(path: String) -> NSURL // Better to use fileURLWithPath:isDirectory: if you know if the path is a directory vs non-directory, as it saves an i/o.
for the line: if var template = NSString(contentsOfURL: templateURL, encoding: NSUTF8StringEncoding)?
Its decleration is:
convenience init(contentsOfURL url: NSURL, encoding enc: UInt) throws
convenience init(contentsOfFile path: String, encoding enc: UInt) throws
So it not returns optional NSString either, so you cannot use if let again. You have to use do-try-catch here.
Apple's document about this:
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID508
Also, you should use multiple unwrapping optional:
if let x = OptionalX, y = OptionalY { ... }
Your code is a pyramid of doom :)

AVRecorder and AVPlayer in swift

All ,
I need to create a sample audio player and recorder, its not erroring but its not playing and perhaps not recording.. any ideas ?
#IBAction func Play(AnyObject)
{
println ("Play")
let path = NSBundle.mainBundle().pathForResource("171010", ofType:"m4a")
let fileURL = NSURL(fileURLWithPath: path)
player = AVAudioPlayer(contentsOfURL: outputFileURL, error: nil)
player.prepareToPlay()
player.delegate = self
player.play()
}
#IBAction func Record(AnyObject)
{
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
settings.setValue(kAudioFormatMPEG4AAC, forKey: AVFormatIDKey)
settings.setValue(44100.0, forKey: AVSampleRateKey)
settings.setValue(2, forKey: AVNumberOfChannelsKey)
recorder = AVAudioRecorder(URL: outputFileURL, settings: settings, error: &error)
recorder.delegate = self;
recorder.prepareToRecord()
recorder.record()
}
#IBAction func Stop(AnyObject)
{
recorder.stop()
println("Stop")
}
and the globals at the top are :
class MainMenu: UIViewController , AVAudioRecorderDelegate , AVAudioPlayerDelegate {
var filename: String!
var outputFileURL: NSURL!
var recorder: AVAudioRecorder!
var error: NSError?
var settings: NSMutableDictionary = NSMutableDictionary()
var player : AVAudioPlayer! = nil
Any ideas ? I don't know if its recording and creating the file. As I am getting URL is nill on the playing function. This is wired up to a storyboard with buttons. Any help within this simple stuff in swift would be brilliant.
I have changed it to this and this should work ? Can anyone advise ?
#IBAction func Play(AnyObject)
{
println ("Play")
var audioPlayer = AVAudioPlayer()
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
audioPlayer = AVAudioPlayer(contentsOfURL: outputFileURL, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.delegate = self
audioPlayer.play()
}
#IBAction func Record(AnyObject)
{
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
settings.setValue(kAudioFormatMPEG4AAC, forKey: AVFormatIDKey)
settings.setValue(44100.0, forKey: AVSampleRateKey)
settings.setValue(2, forKey: AVNumberOfChannelsKey)
recorder = AVAudioRecorder(URL: outputFileURL, settings: settings, error: &error)
recorder.delegate = self;
recorder.prepareToRecord()
recorder.record()
}
The player needs to be an ivar so it isn't popped off the stack before playing.
Here is a github project with a functioning recorder if you need more info.
Also, the convention is to start function names with a lowercase character.

Resources