Cannot call value of non-function type 'HTTPURLResponse? - alamofire

It is giving me the Error: Cannot call value of non-function type 'HTTPURLResponse?'
It should be caused by #escaping but I cannot make it work in the sentence below. Please help, Swift 3.0, AlamofireImage.
There are other similar answers but cannot make them work with my code below.
func getNetworkImage(_ urlString: String, completion: #escaping ((UIImage) -> Void)) -> (ImageRequest) {
let queue = decoder.queue.underlyingQueue
let request = Alamofire.request(urlString)
let imageRequest = ImageRequest(request: request)
imageRequest.request.response(
queue: queue,
responseSerializer: Request.imageResponseSerializer(),
completionHandler: { response in
guard let image = response.result.value else {
return
}
let decodeOperation = self.decodeImage(image) { image in
completion(image)
self.cacheImage(image, urlString: urlString)
}
imageRequest.decodeOperation = decodeOperation
}
)
return imageRequest
}

The error message: Cannot call value of non-function type 'HTTPURLResponse?' is telling you that the instance variable value can not be accessed. The bad thing is that it is telling you this in the wrong line of code. That may be the reason why it was so difficult to find.
The structure of the response object has changed. You code:
guard let image = response.result.value else {
return
}
Won't work anymore because the response object is of type DefaultDataResponse not HTTPResponse...
In order to access the data/image you need to go with response.response. depending on what you want to access:
response.response?.value(forKey: "")
Check the other method calls and properties. I believe you will find the data you are looking for.

Related

Decoding an Error Response using Alamofire 5 and the responseDecodable function

I'm writing an API Client for WooCommerce using Alamofire 5 (beta 1) which will allow me to get orders, coupons etc as well as create them. Note I am using the new .responseDecodable function.
I've set up my API client using the following performRequest function that looks like this:
#discardableResult
private static func performRequest<T:Decodable>(route: APIConfiguration,
decoder: JSONDecoder = JSONDecoder(),
completion: #escaping (Result<T>)->Void) -> DataRequest {
return AF.request(route)
.responseDecodable(decoder: decoder) { (response: DataResponse<T>) in
completion(response.result)
}
}
This works well, since I can, for instance, call a function getCouponForId(_ id: Int) which will execute this function and have the response returned through the completion handler.
The only downfall is that, say the user tries to access a coupon that does not exist, they will receive an error (404 from the server). I can switch on the result to determine either a success or failure case, but Alamofire attempts to decode the body of the error response into the Coupon model I have created.
Going forward, I have created an error model which I intend to have the error decoded using. But with that said, I'm having trouble implementing it into this function.
Does anyone have any ideas on how I could handle this?
(I have created this function through following this guide - hopefully, it might provide a bit more context to what I'm doing. https://github.com/AladinWay/NetworkingExample)
Similiar login function from the article you mentioned, updated for current beta of Alamofire 5 and dealing with 404, 401 etc. (via the guard statement)
static func login(email: String, password: String, completion:#escaping (Result<UserCredentials>)->Void) {
performRequest(router: Router.login(email: email, password: password), completion: completion)
AF.request(Router.login(email: email, password: password))
.validate(statusCode: 200..<300)
.responseDecodable { (response: DataResponse<UserCredentials>) in
guard response.result.isSuccess else {
print("šŸ„¶ Error on login: \(String(describing: response.error))")
return
}
completion(response.result)
}
}
Just update
request.responseDecodable(decoder: decoder, completionHandler: { (response: AFDataResponse<T>) in
to
request.responseDecodable(decoder: decoder, completionHandler: { (response: DataResponse<T>) in

Swift JSQMessagesViewController name on top

I am displaying the sender name of the receiver. However, I don't want to display the name on every single text that the person sends. For example, if he/she sends a a message consecutively, I just want it to display the name on top of the first message. I'll provide a screenshot of my chat here:
In other words, I just want it to display the name of the user on the very 'first' message he/she sends. I tried to solve this issue, in the attributedTextForMessageBubbleTopLabelAt with no luck.
I have tried to check if the senderId of the previous message is equal to the previous senderId - and then somehow find out if it can be shown or not. But, this has resulted in many, many failed attempts with optional errors, index out of range, and just simply not working solutions.
This is the code I have right now:
let message = messages[indexPath.item]
switch message.senderId {
case FIRAuth.auth()!.currentUser!.uid:
return nil
break
default:
guard let senderDisplayName = message.senderDisplayName else {
assertionFailure()
return nil
}
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.left
let attributedString = NSAttributedString(string: message.senderDisplayName,
attributes: [
NSParagraphStyleAttributeName: paragraphStyle,
NSBaselineOffsetAttributeName: NSNumber(value: 0)
])
return attributedString
break
}
This is a difficult problem at first to solve when you first look at it. What we need to do is determine if a message is the first in a set of messages. So I created a function to determine wether or not a message is the first one sent by that person.
private func firstMessageInSet(indexOfMessage: IndexPath) -> Bool {
return messages[safe: indexOfMessage.item - 1]?.senderId() == messages[safe: indexOfMessage.item]?.senderId()
}
it simply checks the pervious message's senderId to see if it is the same as the current message.
Then just call that guy in this method:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, attributedTextForMessageBubbleTopLabelAt indexPath: IndexPath!) -> NSAttributedString! {
guard let message = messages[safe: indexPath.item] else { return nil }
return firstMessageInSet(indexOfMessage: indexPath) ? nil : NSAttributedString(string: message.senderDisplayName)
}
This will check if its the first in the set and if it is return the senderDisplayName. Now this is using short hand but is eventually the same as
if firstMessageInSet(indexOfMessage: indexPath) {
return NSAttributedString(string: message.senderDisplayName)
} else {
return nil
}
Hope that that helps you good luck with things šŸ¤–

how to implement multiple local notification not a single notification for swift 3

i have use the single notification , and this is my code:
this is for register the local notification>>>
func registerLocal() {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Yay!")
} else {
print("D'oh")
}
}
}
and this function to schedule the local notification>>>
func scheduleLocal() {
registerCategories()
let center = UNUserNotificationCenter.current()
// not required, but useful for testing!
center.removeAllPendingNotificationRequests()
let content = UNMutableNotificationContent()
content.title = "good morning"
content.body = "ttt123"
content.categoryIdentifier = "alarm"
content.userInfo = ["customData": "fizzbuzz"]
content.sound = UNNotificationSound.default()
var dateComponents = DateComponents()
dateComponents.hour = 23
dateComponents.minute = 18
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
func registerCategories() {
let center = UNUserNotificationCenter.current()
center.delegate = self
let show = UNNotificationAction(identifier: "show", title: "Tell me moreā€¦", options: .foreground)
let category = UNNotificationCategory(identifier: "alarm", actions: [show], intentIdentifiers: [])
center.setNotificationCategories([category])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// pull out the buried userInfo dictionary
let userInfo = response.notification.request.content.userInfo
if let customData = userInfo["customData"] as? String {
print("Custom data received: \(customData)")
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier:
// the user swiped to unlock; do nothing
print("Default identifier")
case "show":
print("Show more informationā€¦")
break
default:
break
}
}
// you need to call the completion handler when you're done
completionHandler()
}
now how can i use this code with the multiple local notification with iOS 10 and different times
thank you .
Use a different request identifier for each notification (otherwise you only see the last notification).
In the above example, ensure request identifier "UUID().uuidString" contains a unique value for each notification request.
You can call the func scheduleLocal() multiple times with different dateComponents to schedule on different dates. Or you can pass a array of dates to this function and run a loop to schedule the notifications according to these dates.
Just make sure that the identifier you pass in UNNotificationRequest(identifier:, content:, trigger:) function is different for each notification.
Hope this helps. :)
Call this function with different parameters. Like i called when app goes background
func applicationDidEnterBackground(_ application: UIApplication) {
setNotification(time: 25,identifier: "notific2")
setNotification(time: 50,identifier: "notific3")
setNotification(time: 90,identifier: "notific4")
}
func setNotification (time : Int,identifier : String)
{
let content = UNMutableNotificationContent()
content.title = "Don't forget"
content.body = "Buy some milk"
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(time),
repeats: false)
let center = UNUserNotificationCenter.current()
// Swift
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if error != nil {
// Something went wrong
}
})
}
Note that your code should works as expected! however, there is a little pitfall.
I think that I almost faced the exact same issue, after I tried to trace the pending notifications, I noted that the only notification that has been added is the last requested one. That's because you are calling in scheduleLocal() function:
// not required, but useful for testing!
center.removeAllPendingNotificationRequests()
Well, it is good to remove any existing notification reminder requests, this would help preventing unnecessary duplicate notifications, but you should call it only once before calling scheduleLocal():
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
// now you could call this function many times...
scheduleLocal()
simply, you don't want to delete each pending notification directly after adding it, instead you delete the whole previous pending notifications and add new ones.
If you want to use multiple local notification than you have to used different identifier for each request.
let request = UNNotificationRequest(identifier: "Stock Changed", content: content, trigger: nil)
Change "Stock Changed" with your different identifier for each request.
You can use loop for multiple request.

what is the proper syntax for the following expression in swift 3?

as you can guess, this is an issue regarding swift's whole API renovation. I've read the documentation extensively but can't seem to lay my finger on a proper workaround.
I am receiving the error
Value of type 'Error' has no member 'userInfo'
on the following line:
else if let secondMessage = error?.userInfo["error"] as? String
of this block:
let query = PFQuery(className: "Images")
query.whereKey("Subject", equalTo: self.subjectName)
query.findObjectsInBackground { (objects, error) -> Void in
if error == nil {
// do something
}else if let secondMessage = error?.userInfo["error"] as? String {
// do something
}
Any suggestions? feel's like I'm missing something painstakingly obvious... dev block i guess :(

Having trouble converting a simple Objective-C block to Swift

Not sure what I'm doing wrong. I'm using this module https://github.com/wenzhaot/InstagramPhotoPicker (the header file for the block is here https://github.com/wenzhaot/InstagramPhotoPicker/blob/master/TWPhotoPicker/TWPhotoPickerController.h)
In Objective-C, the syntax is:
photoPicker.cropBlock = ^(UIImage *image) {
//do something
};
I tried converting it to swift, but I'm getting an error
photoPicker.cropBlock{ (image:UIImage) -> () in
//Do something
//error: cannot invoke 'cropBlock' with an argument list of type '((UIImage) -> ())'
}
How to get it to work?
You're just missing = sign. Also image is implicitly unwrapped optional:
photoPicker.cropBlock = { (image: UIImage!) -> () in
//Do something
}
or
photoPicker.cropBlock = { image in
//Do something
}