Radio/genres error call in the Deezer iOS sdk - deezer

In the iOS SDK v0.9.0-beta6 the call:
[DZRRadio radiosByGenreWithRequestManager:self.requestManager callback:^(DZRObjectList *deezerList, NSError *error) {
if (error) {
BTBLog_Error(#"Request did fail with error : %#", [error description]);
return;
}}];
results in the error:
Error Domain=DZRModelErrorDomain Code=3 "Some object could not be parsed" UserInfo=0x7c11f070 {DZROriginalErrorsKey=(
"Error Domain=DZRModelErrorDomain Code=2 \"The API returned a malformated object (either id or type missing)\" UserInfo=0x7ae55e80 {DZROriginalJSONKey=<CFBasicHash 0x7c1c47d0 [0x4e99528]>{type = immutable dict, count = 3,\nentries =>\n\t0 ...
and it logs a lot of warnings like:
[DZRWarning]: No "type" in the JSON object cannot parse. The object was:
{
id = 153;
radios = (
{
id = 30921;
picture = "http://api.deezer.com/radio/30921/image";
title = Blues;
tracklist = "http://api.deezer.com/radio/30921/tracks";
type = radio;
}
);
title = Blues;
}
Could you please tell me how to fix it? Or is maybe a bug in this SDK version?

Related

Access iCloud Calendar Events - macOS App

I want access the users iCloud Calendar events in an app for macOS. While researching I have found some tutorials for iOS but I couldn't find one that works on macOS. I tried to understand Apples Developer Documentation for EventKit but didn't manage to get it running.
Thats what I did:
1 - Accessing the Event Store
1.1 I have changed the 'com.apple.security.personal-information.calendars' key to YES in the entitlements file (Stack Overflow Question regarding this).
Screenshot of the .entitlement of the Project:
1.2 Afterwards I tried to request the access (in the viewDidLoad)
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatus(for: .event) {
case .authorized:
print("Acess granted")
case .denied:
print("Access denied")
case .notDetermined:
eventStore.requestAccess(to: .event, completion: {
(granted, error) in
if granted {
print("granted \(granted)")
}else {
print("error \(String(describing: error))")
}
})
default:
print("Case default")
}
2 - Getting the Calendar Events
let sources = eventStore.sources
for source in sources{
print(source.title)
for calendar in source.calendars(for: .event){
print(calendar.title)
}
}
// create dates
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let startDate = formatter.date(from: "2019/9/12 0:01")!
let endDate = formatter.date(from: "2019/9/12 23:59")!
let calendars = eventStore.calendars(for: .event)
let predicate = eventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: calendars)
let events = eventStore.events(matching: predicate)
print(calendars)
print(events)
When I run this app I get the following console output:
getCalendarEvents[1970:100712] CoreData: XPC: Unable to load metadata: Error Domain=NSCocoaErrorDomain Code=134070 "An error occurred in the persistent store." UserInfo={Problem=request failed, insufficient permission}
2019-09-23 18:35:24.981947+0200 getCalendarEvents[1970:100712] [error] error: -addPersistentStoreWithType:NSXPCStore configuration:(null) URL:file:///Users/henri/Library/Calendars/Calendar%20Cache options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSPersistentHistoryTrackingKey = {
NSPersistentHistoryTrackingEntitiesToExclude = (
ChangeRequest
);
};
agentOrDaemon = 1;
serviceName = "com.apple.CalendarAgent.database";
} ... returned error Error Domain=NSCocoaErrorDomain Code=134070 "An error occurred in the persistent store." UserInfo={Problem=request failed, insufficient permission} with userInfo dictionary {
Problem = "request failed, insufficient permission";
}
CoreData: error: -addPersistentStoreWithType:NSXPCStore configuration:(null) URL:file:///Users/henri/Library/Calendars/Calendar%20Cache options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSPersistentHistoryTrackingKey = {
NSPersistentHistoryTrackingEntitiesToExclude = (
ChangeRequest
);
};
agentOrDaemon = 1;
serviceName = "com.apple.CalendarAgent.database";
} ... returned error Error Domain=NSCocoaErrorDomain Code=134070 "An error occurred in the persistent store." UserInfo={Problem=request failed, insufficient permission} with userInfo dictionary {
Problem = "request failed, insufficient permission";
}
[]
[]
error nil
I expected two arrays:
[EKCalendar] and [EKEvent]
I think I really need help here, I have tried a lot but I am relatively new to Swift development, could somebody please help me out?
Thank you!
The reason why you are not being able to access the EKEventStore is because you need to provide a description string as to why you want to do that. This string will be used by the MacOS to provide an explanation to the user why your app wants to have access to the user’s calendar. This string should be provided with the NSCalendarsUsageDescription key in the info.plist file of your app as described here. Even though it is often said in the documentation that is needed for iOS applications, that has also been needed for Mac applications since MacOS Mojave as described here.

AWS API Gateway Error Handling with Generated SDK (Swift)

I'm fairly new to AWS and using API Gateway -> Lambda -> RDS. Also, I'm using the generated SDK for Swift in my iOS mobile application that is consuming the API.
The straight forward paths work fine when returning success (200). However, I'm trying to add in more error handling for edge cases. If an API request doesn't find the resource it's expected, I'm trying to return a 404 error. I've added this to the API Integration Response and Method Response appropriately. I can test this and get my error model returned as expected along with the correct HTTP Status code of 404.
However, I'm struggling with how to handle this on the mobile application side. How would this be handled by the generated SDK? It just throws an error in the API call and I expected a way to retrieve my "Error" model object that I've defined.
Here is normal path
Here is failed path with 404
Generated SDK (Swift) method:
public func userUseridentityGet(useridentity: String) -> AWSTask<RSAPI_UserModel> {
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
]
let queryParameters:[String:Any] = [:]
var pathParameters:[String:Any] = [:]
pathParameters["useridentity"] = useridentity
return self.invokeHTTPRequest("GET", urlString: "/user/{useridentity}", pathParameters: pathParameters, queryParameters: queryParameters, headerParameters: headerParameters, body: nil, responseClass: RSAPI_UserModel.self) as! AWSTask<RSAPI_UserModel>
}
At runtime, I get the following logged out when I print the error out:
Error occurred: Error
Domain=com.amazonaws.AWSAPIGatewayErrorDomain Code=1 "(null)"
UserInfo={HTTPBody={
code = 404;
message = "No Result Found.";
"request-id" = "132b8eaa-7b24-11e7-b1fd-d342f0413b7d";
type = NotFound; }, HTTPHeaderFields={type = immutable dict, count = 8, entries => 0 :
x-cache = {contents = "Error
from cloudfront"} 1 : Content-Type = {contents = "application/json"} 3 : x-amzn-requestid =
{contents =
"131a5075-7b24-11e7-87bd-9fcb4cb4e04e"} 4 : Via = {contents = "1.1
bd4761ff0774f9ee778140b91a0431c9.cloudfront.net (CloudFront)"} 6 :
Date = {contents = "Mon, 07 Aug
2017 03:54:13 GMT"} 10 : Content-Length = 134 11 : x-amzn-trace-id =
{contents =
"sampled=0;root=1-5987e464-d3d8f7801b7ae5aa6a52fc1b"} 12 :
x-amz-cf-id = {contents =
"QKpl64W1qDaeo0zlsx2iOwTW0oO_jyPRmMT7ByPKLnen04qiPEeD6w=="} } }
The question is how do I get that de-serialized into my "Error" object model that I've defined? How do I appropriately detect this error condition so I can write logic in my mobile application to handle it?
For a workaround, I've just handled this by manually extracting out the data. If anyone has a better way of dealing with this. I'd definitely be interested.
if let error = task?.error as NSError? {
print("Error occurred: \(error)")
if error.code == 1 {
let httpBody : NSDictionary = (error.userInfo["HTTPBody"] as? NSDictionary)!
print("Code \(httpBody["code"] ?? "none") - Type \(httpBody["type"] ?? "none") - Message \(httpBody["message"] ?? "none") - RequestID \(httpBody["request-id"] ?? "none")")
}
return nil
}

How to get 401 error from servicestack swift client?

First our codes
let req = SignUp()
req.loginName = "abc#abc.com"
req.passWord = "xxx"
do{
let resp = try client.put(req) <---Where we had an error
} catch {
//some error handling
//.....
}
And then, when we input the correct information, everything is fine but when the login credential is wrong, we had expected to get an 401 error with a proper error message, we didn't. And when we traced it trying to find the origin of this, we had traced it back to JsonServicClient.swift (generated from ServiceStack swift plugin for Xcode 7.2), line 266.
public func send<T : JsonSerializable>(intoResponse:T, request:NSMutableURLRequest) throws -> T {
var response:NSURLResponse? = nil
var data = NSData()
do {
data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
var error:NSError? = NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil)
if let dto = self.handleResponse(intoResponse, data: data, response: response!, error: &error) {
//^^^error here, response is null/can't be null
return dto
}
if let e = error {
throw e
}
return T()
} catch var ex as NSError? {
if let e = self.handleResponse(intoResponse, data: data, response: response!, error: &ex) {
return e
}
throw ex!
}
}
So here is the question, how to properly use ServiceStack swift plugin to get 401 error? When the service returns 400, everything is fine. This problem only happens when the servicestack server api returns 401. Which is by design, we supposed to return 401 when a user authentication fails.
This is a bug in Swift's sendSynchronousRequest which sometimes returns a null response which makes it impossible to determine what the server error response was. I've added a fix for this issue in this commit where it will now throw an unknown Error instead of segfaulting but as Swift doesn't return a HTTP Response we can't query it to return any more info about the error, e.g:
do {
try client.post(request)
} catch let responseError as NSError {
//Swift Bug: 401 returns an unitialized response so status is nil
if let status:ResponseStatus = responseError.convertUserInfo() {
}
}
To get the latest version you can either replace to latest JsonServiceClient.swift or delete the JsonServiceClient.swift and Add/Remove a new Service Reference which will download the latest version.
If you can, you can also switch to use the Async API's which doesn't have this issue:
client.postAsync(request)
.error { responseError in
let status:ResponseStatus = responseError.convertUserInfo()!
status.errorCode //= Unauthorized
}

How to check if a record is on 2 different tables?

I'm using Parse.com and looking for an efficient way of handling this problem.
I have a Sales table which has a User reference column and an Offer reference column.
The Sales table keeps track of which users came in to claim an offer (i.e. 10% discount).
So I have the following subclasses
Offers
Users
Sales
I want to display all available offers but set a local hasBeenUsed flag so that I can display the Offers differently if they have already been used.
At the moment I can create a local array of available Offers but I'm not sure how to set this hasBeenUsed flag accordingly.
var query = Message.query()
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
for object in objects {
var offer = Offer()
offer.info = object["info"] as String
if (also on the Sales list)
offer.hasBeenUsed = true
}
self.offers.insert(offer, atIndex: 0)
}
}
Caveat: Please pardon any Swift errors I make. I am still writing exclusively in Objective-C and I've tried my best to write good Swift, but I am not yet an expert in the syntax.
The best answer I can come up with is that you'll need 2 queries (and this assumes you care about Sales for [PFUser currentUser] or PFUser.currentUser()):
Get the list of Sales objects for the current user
Get the list of all (current) Offer objects.
Query 1
Swift Version
var query = PFQuery(className:"Sales")
query.includeKey("Offer")
query.whereKey("User", equalTo:PFUser.currentUser())
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
// Assign the objects to a property or something
self.sales = objects
// **Then**, run query 2
runQuery2()
} else {
// Do error handling...
}
}
Objective-C Version
PFQuery *query = [PFQuery queryWithClassName:#"Sales"];
[query includeKey:#"Offer"];
[query whereKey:#"User" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error != nil) {
// Do error handling
} else {
// Assign the objects to a property or something...
self.sales = objects;
// **Then**, run query 2
[self runQuery2];
}
}
];
Query 2
Swift Version
var query = PFQuery(className:"Offers")
// Whatever query constraints you need to get "current" offers
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
// Assign the objects to a property or something
self.offers = objects;
// At this point, you have all the data you need, so call the "filter" method
filter()
} else {
// Do error handling...
}
}
Objective-C Version
PFQuery *query = [PFQuery queryWithClassName:#"Offers"];
// Whatever query constraints you need to get "current" offers
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error != nil) {
// Do error handling
} else {
// Assign the objects to a property or something
self.offers = objects;
// At this point, you have all the data you need, so call the "filter" method
[self filter];
}
}
];
Filter Method
This assumes 2 properties: "sales", an array of sales for the current user, and "offers", an array of all current offers
Swift Version
// First, get all of the "redeemed" offers into an array
var localOffers = [PFObject]()
for sale in self.sales {
localOffers.append(sale.offer)
// It might be easier to do it this way
// localOffers.append(sale.offer.objectId)
}
// Next, iterate the "all offers" array and mark each offer as redeemed/not redeemed
for offer in self.offers {
if (localOffers.containsObject(offer)) {
// Alternative check
// if (localOffers.containsObject(offer.objectId)) {
offer.hasBeenUsed = true
} else {
offer.hasBeenUser = false
}
}
Objective-C Version
// First, get all of the "redeemed" offers into an array
NSMutableArray *localOffers = [NSMutableArray array];
for (PFObject *sale in self.sales) {
[localOffers addObject:sale.offer];
// It might be easier to do it this way
// [localOffers addObject:self.offer.objectId];
}
// Next, iterate the "all offers" array and mark each offer as redeemed/not redeemed
for (PFObject *offer in self.offers) {
if ([localOffers containsObject:offer]) {
// Alternative check
// if ([localOffers containsObject:offer.objectId]) {
offer[#"hasBeenUsed"] = #(YES);
} else {
offer[#"hasBeenUsed"] = #(NO);
}
}
At this point, you've got what you need to display the data differently based upon whether the offer has been redeemed or not. Just be careful not to save the hasBeenUsed values to Parse unless that's what you intend.

Cannot publish Facebook Open Graph Post in Swift

FBRequestConnection.startForPostOpenGraphObject(graphObject, {connection, result, error in
if(!error) {
var objectID : NSString = result.objectforKey("id")
println(objectID)
} else {
println(error.description)
}
})
I'm getting the following error on the expression:
Cannot convert the expression's type 'FBRequestConnection!' to 'Void'
I have looked all over SO but couldn't find a solution. Any ideas?
Help would be much appreciated. Thanks.
Maybe check your handler syntax. It should be something like:
let handler:FBRequestHandler = { (connection : FBRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if (error != nil) {
println(error)
} else {
println(result)
}
}
Myself, I'm struggling with getting FBOpenGraphObject from FBGraphObject.openGraphObjectForPost()