get all the tracks from playlist Spotify - ios

I was able to get all the playlist of users using spotify ios sdk, this is my code.
[SPTPlaylistList playlistsForUserWithSession:session callback:^(NSError *error, id object) {
SPTListPage *pl= object;
NSLog(#"%#",pl.items);
}];
But I am not sure now How to get all the tracks of these playlists. any help?

Because this Spotify ios SDK v10beta is new and with many incomplete tasks, to access and be able to play all tracks in your playlists you have to run through many blocks.
First I would recommend to get the first SPTListPage object of all the playlists:
-(void)getFirstPlaylistPage
{
[SPTPlaylistList playlistsForUserWithSession:[SPTAuth defaultInstance].session callback:^(NSError *error, SPTListPage *playlistsPage) {
if (error != nil) {
NSLog(#"*** Getting playlists got error: %#", error);
return;
}
if (playlistsPage==nil) {
NSLog(#"*** No playlists were found for logged in user. ***");
return;
}
[self getFullPlaylistPage:playlistsPage];
}];
}
Then, merge all SPTListPage objects into one:
-(void)getFullPlaylistPage:(SPTListPage*)listPage {
if (listPage.hasNextPage) {
[listPage requestNextPageWithSession:[SPTAuth defaultInstance].session callback:^(NSError *error, SPTListPage* playlistPage) {
if (error != nil) {
NSLog(#"*** Getting playlist page got error: %#", error);
return;
}
listPage = [listPage pageByAppendingPage:playlistPage];
[self getFullPlaylistPage:listPage];
}];
} else {
NSMutableArray* playlist = [[NSMutableArray alloc]init];
[self convertPlaylists:listPage arrayOfPlaylistSnapshots:playlist positionInListPage:0];
}
}
Now, SPTListPage contains SPTPartialPlaylist objects, which do not contain all the info of the playlists, so we need to convert it to SPTPlaylistSnapshot object:
-(void)convertPlaylists:(SPTListPage*)playlistPage arrayOfPlaylistSnapshots:(NSMutableArray*)playlist positionInListPage:(NSInteger)position
{
if (playlistPage.items.count > position) {
SPTPartialPlaylist* userPlaylist = playlistPage.items[position];
[SPTPlaylistSnapshot playlistWithURI:userPlaylist.uri session:[SPTAuth defaultInstance].session callback:^(NSError *error, SPTPlaylistSnapshot* playablePlaylist) {
if (error != nil) {
NSLog(#"*** Getting playlists got error: %#", error);
return;
}
if(!playablePlaylist){
NSLog(#"PlaylistSnapshot from call back is nil");
return;
}
[playlist addObject:playablePlaylist];
[self convertPlaylists:playlistPage arrayOfPlaylistSnapshots:playlist positionInListPage:position+1];
}];
} else {
// send your array of playlists somewhere example:
[self addSongs];
}
}
Now you can access all the playlists and all the songs in them with a simple loop-through.
I hope spotify will improve here as it is not how it supposed to be. Come on,Spotify!

Using Swift3:
After authentication, define a playlist request , like this:
let playListRequest = try! SPTPlaylistList.createRequestForGettingPlaylists(forUser: userName, withAccessToken: token)
I use alamofire to post this request:
Alamofire.request(playListRequest)
.response { response in
let list = try! SPTPlaylistList(from: response.data, with: response.response)
for playList in list.items {
if let playlist = playList as? SPTPartialPlaylist {
print( playlist.name ) // playlist name
print( playlist.uri) // playlist uri
let stringFromUrl = playlist.uri.absoluteString
let uri = URL(string: stringFromUrl)
// use SPTPlaylistSnapshot to get all the playlists
SPTPlaylistSnapshot.playlist(withURI: uri, accessToken: token!) { (error, snap) in
if let s = snap as? SPTPlaylistSnapshot {
// get the tracks for each playlist
print(s.name)
for track in s.firstTrackPage.items {
if let thistrack = track as? SPTPlaylistTrack {
print(thistrack.name)
}
}
}
}
}
}
}

Related

Spotify New iOS SDK (SPTRemoteApp and SPTSessionManger) in iOS

As Spotify framework is upgraded and new classes like SPTRemoteApp has
been introduced, I got totally frustrated to integrate it in old app
as they have changed almost every thing. So I need help if someone can
tell me these following points how it works. Somehow I feel I can do
login part but about track list and its playback part seems not
properly understandable from the Spotify developer docs for iOS.
How to get login Url from new Spotify framework or how to login by clicking button without checking login URL content.
How to get playlist like previously we get playlist by calling this method
[SPTRequest playlistsForUserInSession:session callback:^(NSError *error, SPTListPage *object) {
playListCount = [object.items count] - 1;
if (object.items) {
[object.items enumerateObjectsUsingBlock:^(SPTPartialPlaylist *obj, NSUInteger idx, BOOL *stop) {
[playlistURI addObject:obj.uri];
if (idx == object.items.count - 1) {
[weakSelf requestsTracks:playlistURI withSession:session];
}
spotifySynching = NO;
}];
}else{
spotifySynching = NO;
[self stopAnimatingTotalSpinner];
[self updateProgressDisplays];
}
}];
How to maintain and renew session, nd when we should renew it.
What is the replacement of these methods
(SPTListPage *)object;
[object requestNextPageWithSession:session callback:^(NSError *error, SPTListPage *object) {
[tracksURI addObjectsFromArray:object.items];
if ([object hasNextPage]) {
[self hasNextTrack:object withSession:session withNewObject:newObject];
}else{
[self requestsTracks:newObject withSession:session];
}
}];
[SPTRequest requestItemAtURI:obj withSession:session callback:^(NSError *error, SPTPlaylistSnapshot *object) {
if (error != nil) {
NSLog(#"*** Auth error: %#", error);
return;
}
[tracksURI addObjectsFromArray:object.firstTrackPage.items];
if ([object.firstTrackPage hasNextPage]) {
[self hasNextTrack:object.firstTrackPage withSession:session withNewObject:newObject];
}else{
[self requestsTracks:newObject withSession:session];
}
}];
Please check and let me know.
Thanks

Share videos on Twitter via iOS App

Is it possible to share a video using SLRequest ?
I'm able to share Images using the same
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:requestURL parameters:message];
if (isImage)
{
NSData *data = UIImagePNGRepresentation(imgSelected);
[postRequest addMultipartData:data withName:#"media" type:#"image/png" filename:#"TestImage.png"];
}
postRequest.account = account;
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (!error)
{
NSLog(#"Upload Sucess !");
}
}];
I have been reading through the Twitter Video upload API documentation and its really pretty simple. You basically need to make 3 POST requests to their API. The video you are uploading is also limited to 15 MB in size.
Uploads using this endpoint require at least 3 calls, one to
initialize the request, which returns the media_id, one or more calls
to append/upload binary or base64 encoded data, and one last call to
finalize the upload and make the media_id usable with other resources.
So it works like this:
Request 1: Send a init request with the video size in bytes. This will return a Media ID number which we have to use in request 2 and 3.
Request 2: Use the returned Media ID number from request 1 to upload the video data.
Request 3: Once the video upload has finished, send a "FINALIZE" request back to the Twitter API. This lets the Twitter API know that all the chunks of the video file has finished uploading.
Note The Twitter API accepts video uploads in "chunks". So if your video file is quite big, you may want to split it up into more than one file and thus you will have to repeat "Request 2" more than once (not forgetting to increment the "segment_index" number each time).
I have had a go at coding this below. Try it and experiment around with it. I will update my answer later on to improve it too.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Assign the mediatype to a string
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
// Check the media type string so we can determine if its a video
if ([mediaType isEqualToString:#"public.movie"]) {
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSData *webData = [NSData dataWithContentsOfURL:videoURL];
// Get the size of the file in bytes.
NSString *yourPath = [NSString stringWithFormat:#"%", videoURL];
NSFileManager *man = [NSFileManager defaultManager];
NSDictionary *attrs = [man attributesOfItemAtPath:yourPath error: NULL];
UInt32 result = [attrs fileSize];
//[self tweetVideoStage1:webData :result];
[self tweetVideo:webData :result :1 :#"n/a"];
}
}
-(void)tweetVideo:(NSData *)videoData :(int)videoSize :(int)mode :(NSString *)mediaID {
NSURL *twitterVideo = [NSURL URLWithString:#"https://upload.twitter.com/1.1/media/upload.json"];
// Set the parameters for the first twitter video request.
NSDictionary *postDict;
if (mode == 1) {
postDict = #{#"command": #"INIT",
#"total_bytes" : videoSize,
#"media_type" : #"video/mp4"};
}
else if (mode == 2) {
postDict = #{#"command": #"APPEND",
#"media_id" : mediaID,
#"segment_index" : #"0",
#"media" : videoData };
}
else if (mode == 3) {
postDict = #{#"command": #"FINALIZE",
#"media_id" : mediaID };
}
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:requestURL:twitterVideo parameters:postDict];
// Set the account and begin the request.
postRequest.account = account;
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (!error) {
if (mode == 1) {
// Parse the returned data for the JSON string
// which contains the media upload ID.
NSMutableDictionary *returnedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error]
NSString *tweetID = [NSString stringWithFormat:#"%#", [returnedData valueForKey:#"media_id_string"]];
[self tweetVideo:videoData :result :2 :tweetID];
}
else if (mode == 2) {
[self tweetVideo:videoData :result :3 :mediaID];
}
}
else {
NSLog(#"Error stage %d - %", mode, error);
}
}];
}
Update - Twitter API errors - https://dev.twitter.com/overview/api/response-codes
In answer to your first comment, error 503 means that the Twitter servers are overloaded and can't handle your request right now.
503 Service Unavailable The Twitter servers are up, but overloaded
with requests. Try again later.
I know how to upload video to twitter use the new API. And I have tried it, it works.
Please check this: https://github.com/liu044100/SocialVideoHelper
You just need to call this class method.
+(void)uploadTwitterVideo:(NSData*)videoData account:(ACAccount*)account withCompletion:(dispatch_block_t)completion;
Hope it can resolve your problem.
Best Regards.
Been looking for sharing video on Twitter solution with below features:
Support chunk upload
Built-in support for user's credential retrieval
Since I couldn't find one meeting my need, so I decided to write one.
https://github.com/mtrung/TwitterVideoUpload
I've been testing for awhile now and it works well for me.
Hope it helps,
Regards.
Try this based in #Dan answer. It not tested, but I think it can work.
Use Cocoa-pods: pod 'TwitterKit'
if you don't use Pods try with fabric
//for Extern call
//Mode is 1
//MediaId is 0
- (void)uploadTwitterVideo:(NSData*)videoData videoTitle:(NSString *)title desc:(NSString *)desc withMode:(int)mode mediaID:(NSString *)mediaID withCompletion:(dispatch_block_t)completion
{
NSString *twitterPostURL = #"https://upload.twitter.com/1.1/media/upload.json";
NSDictionary *postParams;
if (mode == 1) {
postParams = #{#"command": #"INIT",
#"total_bytes" : [NSNumber numberWithInteger: videoData.length].stringValue,
#"media_type" : #"video/mp4"};
} else if (mode == 2) {
postParams = #{#"command": #"APPEND",
#"media_id" : mediaID,
#"segment_index" : #"0"};
} else if (mode == 3) {
postParams = #{#"command": #"FINALIZE",
#"media_id" : mediaID };
} else if (mode == 4) {
postParams = #{#"status": desc,
#"media_ids" : #[mediaID]};
}
TWTRAPIClient *twitterInstance = [[Twitter sharedInstance] APIClient];
NSError *error;
NSURLRequest *requestTw = [twitterInstance URLRequestWithMethod:#"POST" URL:twitterPostURL parameters:postParams error:&error];
[twitterInstance sendTwitterRequest:requestTw completion:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(#"HTTP Response: %li, responseData: %#", (long)response, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
if (error) {
NSLog(#"There was an error:%#", [error localizedDescription]);
} else {
if (mode == 1) {
NSMutableDictionary *returnedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&connectionError];
NSString *mediaIDResponse = [NSString stringWithFormat:#"%#", [returnedData valueForKey:#"media_id_string"]];
NSLog(#"stage one success, mediaID -> %#", mediaID);
[self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:2 mediaID:mediaIDResponse withCompletion:completion];
} else if (mode == 2) {
[self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:3 mediaID:mediaID withCompletion:completion];
} else if (mode == 3) {
[self uploadTwitterVideo:videoData videoTitle:title desc:desc withMode:4 mediaID:mediaID withCompletion:completion];
} else if (mode == 4) {
DispatchMainThread(^(){completion();});
}
}
}];
}
This API Works as follows.
- Login when application (twitter) is installed and when is not installed
- First priority take credential from setting
Check this case
Swift
Its very Simple.
First you need to sign in to your Twitter Account. Go to Phone Setting and click on twitter app and sign in.
Now Just Call this videoUpload func anywhere
Video or Chunked uploads Method Reference
Replace your video type/extension on that code
And Carefully read all twitter requirements.
var twitterAccount = ACAccount()
func videoUpload{
let path = Bundle.main.path(forResource: "file-Name", ofType:"mp4")
let filePath = path
var fileSize = UInt64()
do {
//return [FileAttributeKey : Any]
let attr = try FileManager.default.attributesOfItem(atPath: filePath!)
fileSize = attr[FileAttributeKey.size] as! UInt64
//if you convert to NSDictionary, you can get file size old way as well.
let dict = attr as NSDictionary
fileSize = dict.fileSize()
} catch {
print("Error: \(error)")
}
let accountStore = ACAccountStore()
let twitterAccountType = accountStore.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
accountStore.requestAccessToAccounts(with: twitterAccountType, options: nil) { (granted, error) in
if granted {
let accounts = accountStore.accounts(with: twitterAccountType)
if (accounts?.count)! > 0 {
self.twitterAccount = accounts?.last as! ACAccount
}}}
twitterAccount = Twitter.sharedInstance().sessionStore.session() as! ACAccount
uploadVideoToTwitter(videoURL: URL(string : path!)! as NSURL, fileSize: UInt32(fileSize))
}
func uploadVideoToTwitter(videoURL:NSURL,fileSize: UInt32) {
if let videoData = NSData(contentsOfFile: videoURL.path!){
self.tweetVideoInit(videoData: videoData, videoSize: Int(fileSize))
}
}
func tweetVideoInit(videoData:NSData,videoSize:Int) {
let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
var params = [String:String]()
params["command"] = "INIT"
params["total_bytes"] = String(videoData.length)
params["media_type"] = "video/mp4"
let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
requestMethod: SLRequestMethod.POST,
url: uploadURL as URL!,
parameters: params)
postRequest?.account = self.twitterAccount;
postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
if let err = error {
print(error as Any)
}else{
do {
let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
if let tweetID = dictionary["media_id_string"] as? String{
self.tweetVideoApped(videoData: videoData, videoSize: videoSize, mediaId: tweetID, chunk: 0)
}
}
}
catch {
print(error)
}
}
})
}
func tweetVideoApped(videoData:NSData,videoSize:Int ,mediaId:String,chunk:NSInteger) {
let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
var params = [String:String]()
params["command"] = "APPEND"
params["media_id"] = mediaId
params["segment_index"] = String(chunk)
let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
requestMethod: SLRequestMethod.POST,
url: uploadURL as URL!,
parameters: params)
postRequest?.account = self.twitterAccount
postRequest?.addMultipartData(videoData as Data!, withName: "media", type: "video/mov", filename:"mediaFile")
postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
if let err = error {
print(err)
}else{
self.tweetVideoFinalize(mediaId: mediaId)
}
})
}
func tweetVideoFinalize(mediaId:String) {
let uploadURL = NSURL(string:"https://upload.twitter.com/1.1/media/upload.json")
var params = [String:String]()
params["command"] = "FINALIZE"
params["media_id"] = mediaId
let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
requestMethod: SLRequestMethod.POST,
url: uploadURL as URL!,
parameters: params)
postRequest?.account = self.twitterAccount;
postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
if let err = error {
print(err)
}else{
do {
let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
self.postStatus(mediaId: mediaId)
}
}
catch {
print(error)
}
}
})
}
func postStatus(mediaId:String) {
let uploadURL = NSURL(string:"https://api.twitter.com/1.1/statuses/update.json")
var params = [String:String]()
params["status"] = "my first Video Upload"
params["media_ids"] = mediaId
let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter,
requestMethod: SLRequestMethod.POST,
url: uploadURL as URL!,
parameters: params)
postRequest?.account = self.twitterAccount;
postRequest?.perform(handler: { ( responseData, urlREsponse,error) in
if let err = error {
print(err)
}else{
do {
let object = try JSONSerialization.jsonObject(with: responseData! as Data, options: .allowFragments)
if let dictionary = object as? [String: AnyObject] {
print("video uploaded")
}
}
catch {
print(error)
}
}
})
}
I was able to upload video to twitter successfully!
Below are steps referred from twitter docs:
Request for twitter account
accountStore.requestAccessToAccounts(with: twitterAccountType,options:nil){(granted, error) in
POST media/upload (INIT)
params["command"] = "INIT"
params["total_bytes"] = String(videoData.length)
params["media_type"] = "video/mov"
POST media/upload (APPEND)
params["command"] = "APPEND"
params["media_id"] = mediaId
params["segment_index"] = String(chunk)
POST media/upload (FINALIZE)
params["command"] = "FINALIZE"
params["media_id"] = mediaId
POST media/upload
params["status"] = twitterDescription
params["media_ids"] = mediaId
Here is twitter doc link https://dev.twitter.com/rest/media/uploading-media.html
Please fine the detailed solution for video upload to twitter using SLRequest here.
http://swiftoverflow.blogspot.in/2017/04/upload-video-to-twitter-using-slrequest.html

Can't fetch parse file from PFObject

Trying to fetch a PFfile from PfObject but when I fetch value of a particular key , it only gives me a class name
Here is my CloudCode
Parse.Cloud.define("fetchBusinessWithID", function(request, response) {
var query = new Parse.Query("Business");
query.equalTo("uniqueBusinessID", request.params.businessId);
query.find({
success: function(results) {
if(results.length > 0)
{
var fetchedObject = results[0];
response.success(fetchedObject);
}
else
{
response.error("No Business Saved Yet");
}
},
error: function() {
response.error("Something Went wrong");
}
});
});
And this is on iOS
PFCloud callFunctionInBackground:#"fetchBusinessWithID"
withParameters:#{#"businessId": #"Madept2"}
block:^( PFObject *business, NSError *error) {
}];
When I see PFObject in Debug console
So how can I fetch attributes of this file, as I can not parse full object of PfFile, Please help me on this, What I am doing wrong.
Here is my data Model
Get your image data with:
PFFile *imageFile = [business objectForKey:#"aboutImage"];
[imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
if (error == nil) {
UIImage *aboutImage = [UIImage imageWithData:result];
// use your image
}
}];

Retrieve users top score from Game Center with swift

I need to retrieve a player's top submitted score from Game Center. I think I found the answer in objective C, but I don't know how to write it in swift since I am fairly new to this. Can someone help me translate the following code into swift? Thank you in advance.
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil) {
[leaderboardRequest loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error){
if (error != nil) {
//Handle error
}
else{
[delegate onLocalPlayerScoreReceived:leaderboardRequest.localPlayerScore];
}
}];
}
Here's a straight translation to Swift:
let leaderboardRequest = GKLeaderboard() as GKLeaderboard!
if leaderboardRequest != nil
{
leaderboardRequest.loadScoresWithCompletionHandler({ (scores:[AnyObject]!, error:NSError!) -> Void in
if error != nil
{
//handle error
}
else
{
delegate.onLocalPlayerScoreReceived(leaderboardRequest.localPlayerScore)
}
})
}

Any working sample code for CKDiscoverAllContactsOperation for IOS8 beta CloudKit?

I have been playing with icloud in the ios 8 beta, and the CloudKitAtlasAnIntroductiontoCloudKit sample project has been very helpful.
https://developer.apple.com/library/prerelease/ios/samplecode/CloudAtlas/Introduction/Intro.html
But I wanted to use the CKDiscoverAllContactsOperation class and I cannot find any sample code for it anywhere at all and the online documentation is not very helpful.
https://developer.apple.com/library/prerelease/ios/documentation/CloudKit/Reference/CKDiscoverAllContactsOperation_class/index.html
If anyone has managed to successfully use CKDiscoverAllContactsOperation could you please help point me in the right direction or show a working example of how it should be called?
I have tried this to see if I could even get an response from iCloud but nothing:
- (void)queryForRecordsOtherUsersInAddressBookcompletionHandler:(void (^)(NSArray *records))completionHandler {
CKDiscoverAllContactsOperation *discoverAllContactsOperation= [[CKDiscoverAllContactsOperation alloc] init];
[discoverAllContactsOperation setContainer:_container];
NSMutableArray *results = [[NSMutableArray alloc] init];
discoverAllContactsOperation.discoverAllContactsCompletionBlock = ^(NSArray *userInfos, NSError *operationError) {
[results addObjectsFromArray:userInfos];
};
discoverAllContactsOperation.discoverAllContactsCompletionBlock=^(NSArray *userInfos, NSError *operationError){
if (operationError) {
// In your app, handle this error with such perfection that your users will never realize an error occurred.
NSLog(#"An error occured in %#: %#", NSStringFromSelector(_cmd), operationError);
abort();
} else {
dispatch_async(dispatch_get_main_queue(), ^(void){
completionHandler(results);
});
}
};
}
and calling with this...
[self.cloudManager queryForRecordsOtherUsersInAddressBookcompletionHandler:^(NSArray *records ) {
if (records.count==0){
NSLog(#"Login name not found");
return;
}
//self.results= records;
//_loggedInRecord = self.results[0];
//NSLog(#"%#,%#",_loggedInRecord[#"lastName"],_loggedInRecord[#"firstName"]);
// [self performSegueWithIdentifier:#"loggedInSegue" sender:self ];
}];
I know the code shouldn't really do anything. Again I was just looking for a response from iCloud.
Here is what I am using. self.container is a CKContainer set with [CKContainer defaultContainer] in the init.
-(void)queryForAllUsers: (void (^)(NSArray *records))completionHandler {
CKDiscoverAllContactsOperation *op = [[CKDiscoverAllContactsOperation alloc] init];
[op setUsesBackgroundSession:YES];
op.queuePriority = NSOperationQueuePriorityNormal;
[op setDiscoverAllContactsCompletionBlock:^(NSArray *userInfos, NSError *error) {
if (error) {
NSLog(#"An error occured in %#: %#", NSStringFromSelector(_cmd), error);
//abort();
} else {
// NSLog(#"Number of records in userInfos is: %ld", (unsigned long)[userInfos count]);
dispatch_async(dispatch_get_main_queue(), ^(void){
completionHandler(userInfos);
});
}
}];
[self.container addOperation:op];
}
Before you can use the CKDiscoverAllContactsOperation operation, you first need to request for permission.
Pls use the method requestApplicationPermission:completion:
func discoverAllContacts() {
let container = CKContainer.defaultContainer()
//Request for user permission
container.requestApplicationPermission([.UserDiscoverability]) { [weak self] status, error in
switch status {
case .Granted where error == nil:
let operation = self?.discoverAllContactsOperation { usersInfo in
//do something here
}
if let operationExists = operation {
//Assuming there is a NSOperationQueue property called operationQueue
self?.operationQueue.addOperation(operationExists)
}
default:
break
}
}
}
func discoverAllContactsOperation(completionHandler: ([CKDiscoveredUserInfo]?) -> ()) -> NSOperation {
let operation = CKDiscoverAllContactsOperation()
operation.discoverAllContactsCompletionBlock = { usersInfo, error in
if error == nil {
print("Discoverd all contacts = \(usersInfo)")
completionHandler(usersInfo)
}
else {
print("Discoverd all contacts error = \(error)")
completionHandler(nil)
}
}
return operation
}

Resources