SPTTrack trackWithURI issue - ios

I had created the new project which fetches the track of songs, so I tried to pass an array of SPTTracks to the player, please find it below.
self.player = [[SPTAudioStreamingController alloc] initWithClientId:auth.clientID];
self.player.diskCache = [[SPTDiskCache alloc] initWithCapacity:1024 * 1024 * 64];
NSString *trackURI = #"spotify:track:1zHlj4dQ8ZAtrayhuDDmkY";
[SPTTrack trackWithURI:[NSURL URLWithString:trackURI] accessToken:auth.session.accessToken market:#"ES" callback:^(NSError *error, id object) {
if (!error) {
SPTTrack *trackInfo = object;
NSArray *tracks = #[trackInfo];
[self.player playURIs:tracks fromIndex:0 callback:^(NSError *error) {
if (!error) {
} else {
NSLog(#"*** Failed to play track : %#", error);
}
}];
} else {
NSLog(#"Error %#", error);
}
}];
But I get crashes, whenever I run it. Please find error below while it is getting crash :
Simple Track Playback[254:24669] -[__NSCFConstantString absoluteString]: unrecognized selector sent to instance 0x1000c0508
I had also looked it on spotify api spotify_ios_sdk but I had found that one developer had already posted the same issue link.
If anyone has solved these type of issue then please provide your guidance.
Thanks in advanced.

Unfortunately, this method is not "equivalent", because the SPTTrack object returned inside the callback of [SPTTrack trackWithURI.... has many less informations.
I've tried some workaround, and I found that for me the solution is
1) Create a request for an SPTTrack object.
2) Pass that request to SPRequest performRequest callback.
3) Wait for the response, and eventually create a track from data (please find the below complete code).
self.player = [[SPTAudioStreamingController alloc] initWithClientId:auth.clientID];
self.player.diskCache = [[SPTDiskCache alloc] initWithCapacity:1024 * 1024 * 64];
NSString *market = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
NSURLRequest *request = [SPTTrack createRequestForTrack:[NSURL URLWithString:#"spotify:track:1zHlj4dQ8ZAtrayhuDDmkY"]
withAccessToken:auth.session.accessToken
market:market
error:nil];
[[SPTRequest sharedHandler] performRequest:request
callback:^(NSError *error, NSURLResponse *response, NSData *data) {
if (!error) {
NSError *parsingError = nil;
SPTTrack *track = [SPTTrack trackFromData:data
withResponse:response
error:&parsingError];
self.arrURIs = #[track.playableUri];
[self.player playURIs:self.arrURIs fromIndex:0 callback:nil];
}
}];
Thanks "Kry256" for detail explaination.

Related

How can I add Status code to an Error?

I have a 'JSON' data with different status codes, as shown in the image, I'm using 'AFHTTPSessionManager', And if we call the API I get 200 as success code, Apart from that in my response object I have status codes So I want to do different operations based on the status codes, For this I have written code like this..
-(void)validateOTP:(NSString *)OTP andUserID:(NSString *)userID withCompletion:(void(^)(NSDictionary* dictionary, NSError* error))completion
{
UTValidateOTPRequest *request = [UTValidateOTPRequest validateOTPRequestWithOTP:OTP andUserID:userID];
NSDictionary *paramDict = [request dictionaryRepresentation];
NSURLSessionDataTask *task = [self postRequestToResouce:[NSString stringWithFormat:#"%#/ValidateOTP",kServerCommonEndPoint] arguments:paramDict successHandler:^(NSDictionary *response) {
NSNumber *statusCode = response[kStatusCodeKey];
if (statusCode.integerValue == UTStatusCodeSuccess) {
completion(response, nil);
}
else {
NSError *error = [NSError mapStatusCodeToError:statusCode.integerValue details:response];
completion(nil, error);
}
} errorHandler:^(NSError *error) {
NSError *newError = [NSError mapStatusCodeToError:error.code details:error.userInfo];
completion(nil, newError);
}];
[self addDataTask:task];
}
As you can see, even inside success handler I'm passing error and calling a category method we have created.
NSError *error = [NSError mapStatusCodeToError:statusCode.integerValue details:response];
This method implemented as follows
+ (NSError *)mapStatusCodeToError: (NSInteger)statusCode details:(NSDictionary*) errorInfo
{
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *domain = [bundleIdentifier stringByAppendingString:kErrorDomainKey];
NSString *errorMessage = nil;
if (errorInfo[kErrorMessageKey] && ![errorInfo[kErrorMessageKey] isEqualToString:kEmptyString]) {
errorMessage = errorInfo[kErrorMessageKey];
}
else{
// use common message
errorMessage = kInternetNotAvailableMessage;
}
NSDictionary *userInfo = #{NSLocalizedDescriptionKey:NSLocalizedString(errorMessage, nil)};
NSLog(#"User INFO : %#",userInfo);
NSError *internetUnavailableError = [NSError errorWithDomain:domain
code:NSURLErrorNotConnectedToInternet
userInfo:userInfo];
NSLog(#"Error Code : %ld",(long)internetUnavailableError.code);
return internetUnavailableError;
}
Here I want to use the statusCode that I'm passing as parameter to this method so that I can get that status code where I'm calling this method
[[UTServerManager sharedInstance] validateOTP:self.enterOTPText.text andUserID:self.userId withCompletion:^(NSDictionary *dictionary, NSError *error) {
// Here I want to get the status code of error not like -1009 , but what ever statusCode that I'm getting from the API response.
}];
So in this method can I get the response status code if it is not success code means as you see in the image in the first response is success and remaining are error responses.
And I know that I can use the statusCode in the category method but I dont know how to use it, If I store this status-Code in the category method for error as above , that I'm passing as a parameter to the methods then I can call them where ever I require How to get this ?
And my restriction is I should these methods only but I have to add the response status code to error ??
Looks like you are passing a userInfo dict to the NSError. You could add to this dictionary prior to creating the NSError you are returning, and then later it would be available in the NSError callback.

CloudKit: notificationChangedBlock no response

I working in app using CloudKit. I'm implement a way to get deltas from CloudKit to my app (I'm using the public database). I get a response back from fetchNotificationChangesCompletionBlock block but I don't get a response back from notificationChangedBlock.
Here is my code:
-(void)checkForNewData
{
CKServerChangeToken *token = [[cloudKitToken helper] getCloudKitToken];
CKFetchNotificationChangesOperation *op = [[CKFetchNotificationChangesOperation alloc]
initWithPreviousServerChangeToken:token];
NSMutableArray *noteIds = [[NSMutableArray alloc] init];
op.notificationChangedBlock = ^(CKNotification *note)
{
CKNotificationID *noteId = note.notificationID;
[noteIds addObject:noteId];
if([note isKindOfClass:[CKQueryNotification class]]) {
CKQueryNotification *qNote = (CKQueryNotification *)note;
CKRecordID *changedRecordID = qNote.recordID;
NSLog(#"I got CKQueryNotification");
}
};
op.fetchNotificationChangesCompletionBlock = ^(CKServerChangeToken *token, NSError *error) {
NSLog(#"error %#", error.localizedDescription);
};
[[CKContainer defaultContainer] addOperation:op];
}
Any of you knows what I'm doing wrong or what is wrong with my code?
I'll really appreciate your help.

GTLQueryYouTube:queryForVideosListWithIdentifier:part: didn't do anything (Objective C )

I'm trying to use the iOS-GTLYouTube library for displaying videos. So far this is what I've got:
//Get the youtube video list
GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
// Set the APIKey
service.APIKey = #"APIKey";
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithIdentifier:[vidListIds copy] part:#"id,snippet"];
GTLServiceTicket *ticket = [ service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error)
{
// This callback block is run when the fetch completes
if (error == nil)
{
GTLYouTubeVideoListResponse *products = object;
// iteration of items and subscript access to items.
for (GTLYouTubeVideo *item in products)
{
GTLYouTubeVideoSnippetThumbnails *thumbnails = item.snippet.thumbnails;
[thumbnailMutableList addObject:thumbnails];
NSLog(#"Title: %#", item.snippet.title);
}
}
else
{
NSLog(#"Error: %#", error.description);
}
}];
I don't know why but this code didn't seem to do anything. There's neither the "Title:" log nor the "Error" log. I know that it was done in a separate thread so it worked asynchronously. But I've waited for 1-2 minutes and still nothing is shown. Can anybody help me here? Thanks.
Never mind. In the NSMutableString *vidListIds I forgot to append a comma. Silly me. Thanks for reading though. Sorry for the false alarm. :)

No shared download link from boxItem in BoxFolderPickerViewController

How can I get the download_url or shared link from the item returned below? The file id and name, size and date modified are available, but my requirement is to return a download_url or shared link.
- (void)folderPickerController:(BoxFolderPickerViewController *)controller didSelectBoxItem:(BoxItem *)item
{
[self dismissViewControllerAnimated:YES completion:^{
// NSLog("%#",item);
// NSLog(#"%#", item.rawResponseJSON);
if ([BoxSDK sharedSDK].OAuth2Session.isAuthorized){
NSLog(#"authorized");
BoxAPIJSONFailureBlock failure = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSDictionary *JSONDictionary){
[self boxError:error];
};
NSDictionary *const queryParametersDictionary = #{#"fields" : #"item_collection"};
BoxFilesRequestBuilder *builder = [[BoxFilesRequestBuilder alloc] initWithQueryStringParameters:queryParametersDictionary];
BoxAPIJSONOperation *operation= [[BoxSDK sharedSDK].filesManager fileInfoWithID:item.modelID
requestBuilder:builder
success:nil
failure:failure];
}else{NSLog(#"fail");}
}];
Not sure why you'd need download_url. Do you want to expose it to some other app or user?
If you don't see shared_link in your item rawResponseJSON (debugger: po [file rawResponseJSON][#"shared_link"]), then it is highly likely that file is not shared. You need to share it first.
Here is how you do it, given you already have BoxItem
BoxFileBlock success = ^(BoxFile *file) {
dispatch_async(dispatch_get_main_queue(), ^{
self.item = file;
NSDictionary *sharedLinkInfo = [self.item sharedLink];
// here is your urlString of the sharedLink
NSString *urlString = [sharedLinkInfo objectForKey:#"url"];
});
};
BoxFilesRequestBuilder *builder = [[BoxFilesRequestBuilder alloc] init];
builder.sharedLink = [[BoxSharedObjectBuilder alloc] init];
builder.sharedLink.access = BoxAPISharedObjectAccessOpen;
builder.sharedLink.canDownload = BoxAPISharedObjectPermissionStateEnabled;
builder.sharedLink.canPreview = BoxAPISharedObjectPermissionStateEnabled;
[self.sdk.filesManager editFileWithID:self.item.modelID
requestBuilder:builder
success:success
failure:failure];
Ideally you also want to provide failure block (omitted here)
Also make sure that you're using latest SDK. It had a small bug fix for sharedObjectFileBuilder that went in yesterday.

iOS BoxSDK returning nil for sharedLink

We need to create a shared link for a file and then retrieve that link so
that we can display it inside our application.
We are able to create a shared link for a specific file (we can see it
inside Box Account on the Web) but we are not able to retrive sharedLink
via the API. It is always nil, although isShared method returns YES.
From the header file of BoxObject.h we find that these two methods provide
required information about shared state of the item.
#protocol BoxObject
// ...
// Information about the shared state of the item
#property (readonly, getter = isShared) BOOL shared;
#property (readonly) NSString *sharedLink;
//...
#end
This is how we create shared link.
Find BoxFile that we would like to share, lets call that object photo
Prior calling method shareWithPassword:message:emails:callbacks:, [photo
isShared] returns NO.
we call [photo shareWithPassword:#"" message:#"" emails:[NSArray
arrayWithObject:#""] callbacks:^(id<BoxOperationCallbacks>
on1){...}];
inside on1.after we check if response == BoxCallbackResponseSuccessful
and then we call [photo updateWithCallbacks:^(id
on2){..}]
inside on2.after we check if response == BoxCallbackResponseSuccessful
on successful response [photo isShared] returns YES but [photo
sharedLink] returns nil
And if we check on the Web, we can see that file is actually shared but we
cannot retrive sharedLink from the Box SDK.
Anyone has the same problem?
This is working for me, based off of the code already posted and the information found on github here
- (void) getShareableLinkForFileId:(NSString *)fileId
{
BoxFileBlock fileSuccess = ^(BoxFile *file) {
NSDictionary *fileInfo = file.rawResponseJSON;
if (![fileInfo[#"shared_link"] isEqual:[NSNull null]]) {
NSDictionary *linkData = fileInfo[#"shared_link"];
//Do something with the link
} else {
// failure
}
};
BoxAPIJSONFailureBlock failure = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSDictionary *JSONDictionary) {
//Handle the failure
};
BoxFilesRequestBuilder *builder = [[BoxFilesRequestBuilder alloc] init];
BoxSharedObjectBuilder *sharedBuilder = [[BoxSharedObjectBuilder alloc] init];
sharedBuilder.access = BoxAPISharedObjectAccessOpen;
builder.sharedLink = sharedBuilder;
[[BoxSDK sharedSDK].filesManager editFileWithID:fileId requestBuilder:builder success:fileSuccess failure:failure];
}
I was able to get the share link by refreshing the folder itself. This is the code I came up with:
[boxFile shareWithPassword:#"" message:#"" emails:#[ #"" ] callbacks:^(id<BoxOperationCallbacks> on) {
on.after(^(BoxCallbackResponse response) {
if (response == BoxCallbackResponseSuccessful) {
[self.rootFolder updateWithCallbacks:^(id<BoxOperationCallbacks> on) {
on.after(^(BoxCallbackResponse response) {
BoxFile *updatedBoxFile = (BoxFile*)[self.rootFolder.children objectAtIndex:self.selectedIndexPath.row];
NSString *fileName = updatedBoxFile.name;
NSString *shareLink = updatedBoxFile.sharedLink;
NSLog(#"%# [%#]: %#", fileName, updatedBoxFile.isShared ? #"YES" : #"NO", shareLink);
});
}];
} else {
[BoxErrorHandler presentErrorAlertViewForResponse:response];
}
});
}];
This is with the old v1 API. Not sure if it has changed with the newer v2.
You can create a shared link by edit its info with Box V2:
Box2FolderBlock folderSuccess = ^(Box2Folder *folder) {
if (![[folder sharedLink] isEqual:[NSNull null]]) {
NSString *sharedUrl = [[folder sharedLink] objectForKey:Box2APIObjectKeyURL];
} else {
// failure
}
};
Box2FileBlock fileSuccess = ^(Box2File *file) {
if (![[file sharedLink] isEqual:[NSNull null]]) {
NSString *sharedUrl = [[file sharedLink] objectForKey:Box2APIObjectKeyURL];
} else {
// failure
}
};
Box2APIJSONFailureBlock failure = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSDictionary *JSONDictionary) {
};
BoxSharedObjectBuilder *sharedLinkObject = [[BoxSharedObjectBuilder alloc] init];
sharedLinkObject.access = BoxAPISharedObjectAccessOpen;
BoxAPIJSONOperation *operation;
if (isFile == NO) {
sharedLinkObject.canPreview = BoxAPISharedObjectPermissionStateEnabled;
BoxFoldersRequestBuilder *requestBuilder = [[BoxFoldersRequestBuilder alloc] init];
requestBuilder.sharedLink = sharedLinkObject;
operation = [boxSDK.foldersManager editFolderWithID:fileOrFolderId requestBuilder:requestBuilder success:folderSuccess failure:failure];
} else {
sharedLinkObject.canDownload = BoxAPISharedObjectPermissionStateEnabled;
BoxFilesRequestBuilder *requestBuilder = [[BoxFilesRequestBuilder alloc] init];
requestBuilder.sharedLink = sharedLinkObject;
operation = [boxSDK.filesManager editFileWithID:fileOrFolderId requestBuilder:requestBuilder success:fileSuccess failure:failure];
}

Resources