get dropbox thumbnails with getThumbnailBatch - ios

I'm using the dropbox objc API and I'm trying to get all thumbnails in a specific dropbox folder.
But I'm completely stuck at DBFILESGetThumbnailBatchArg. How do I initiate paths to all images in a folder?
This is the line I'm stuck at:
[[client.filesRoutes getThumbnailBatch:<#(nonnull NSArray<DBFILESThumbnailArg *> *)#>]
setResponseBlock:^(
DBFILESGetThumbnailBatchResult * _Nullable result,
DBFILESGetThumbnailBatchError * _Nullable routeError,
DBRequestError * _Nullable networkError) { etc etc..
Documentation says
DBFILESThumbnailArg *arg = [[DBFILESThumbnailArg alloc] initWithPath:<#(nonnull NSString *)#>];
DBFILESGetThumbnailBatchArg *batchArg = [[DBFILESGetThumbnailBatchArg alloc]
initWithEntries:<#(nonnull NSArray<DBFILESThumbnailArg *> *)#>];
How do I init a list of paths of DBFILESThumbnailArg?
Link to documentation:
https://dropbox.github.io/dropbox-sdk-obj-c/api-docs/latest/Classes/DBFILESRouteObjects.html#/c:objc(cs)DBFILESRouteObjects(cm)DBFILESGetThumbnailBatch

As you found, the getThumbnailBatch method expects an NSArray<DBFILESThumbnailArg *>, so calling it would look like this:
NSArray<DBFILESThumbnailArg *> *entries = #[[[DBFILESThumbnailArg alloc] initWithPath:#"/test1.jpg"], [[DBFILESThumbnailArg alloc] initWithPath:#"/test2.jpg"]];
[[client.filesRoutes getThumbnailBatch:entries]
setResponseBlock:^(DBFILESGetThumbnailBatchResult *result, DBFILESGetThumbnailBatchError *routeError, DBRequestError *networkError) {
if (result) {
NSLog(#"result:");
NSLog(#"%#", result);
} else if (routeError) {
NSLog(#"routeError:");
NSLog(#"%#", routeError);
} else if (networkError) {
NSLog(#"networkError:");
NSLog(#"%#", networkError);
};
}];

I solved this using a NSMutableArray, posting my solution if others come looking:
//Create a temporary NSMutableArray
NSMutableArray *thumbArgMutable = [[NSMutableArray alloc] init];
for (NSString* image in _images)
{
//Create DBFILESThumbnailArg from NSString
DBFILESThumbnailArg *arg = [[DBFILESThumbnailArg alloc] initWithPath:image];
//Add path as DBFILESThumbnailArg to NSMutableArray
[thumbArgMutable addObject:arg];
}
//Copy NSMutableArray to a new DBFILESThumbnailArg
DBFILESThumbnailArg *thumbArg = [thumbArgMutable copy];
//create a DBFILESGetThumbnailBatchArg and init with the copied DBFILESThumbnailArg
DBFILESGetThumbnailBatchArg *thumbArgBatch = [[DBFILESGetThumbnailBatchArg alloc] initWithEntries:thumbArg];
DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:#"TOKEN"];
//use property entries from DBFILESGetThumbnailBatchArg
[[client.filesRoutes getThumbnailBatch:thumbArgBatch.entries]
setResponseBlock:^(DBFILESGetThumbnailBatchResult * _Nullable result,
DBFILESGetThumbnailBatchError * _Nullable routeError,
DBRequestError * _Nullable networkError)
{
if (result) {
NSLog(#"%#\n", result);
//loop all downloaded thumbnails
for (DBFILESGetThumbnailBatchResultEntry *data in result.entries)
{
//extract data from each base64 encoded thumbnail string
NSData *thumbData = [[NSData alloc] initWithBase64EncodedString:data.success.thumbnail options:0];
//create UIImage from data
UIImage *thumbImage = [UIImage imageWithData:thumbData];
}
}
else { //if download failed
NSLog(#"%#\n%#\n", routeError, networkError);
}

Related

Parse two JSON objects

When i send API i'm getting JSON response like this.
{"ABC":[{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"},{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"},{"ID1":"response","ID2":"response","ID3":"response","ID4":"response","ID5":"response"}],"status":"OK","count":3}
{"XYZ":[{"id1":"response"},{"id1":"response"},{"id1":"response"}],"status":"OK","count":3}
Here i'm getting two JSON objects in the response. How to store this data in MutableArrays.
My code is...
//Getting data from server through JSON approach ...
self.urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
self.urlReq= [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[[NSString alloc] initWithFormat:#"http://MyApiName"]]];
self.dataTask = [self.urlSession dataTaskWithRequest:self.urlReq completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!(data == nil)) {
self.loginDic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"data : %#", data);
NSLog(#"Login Dic : %#", [self.loginDic objectForKey:#"ABC"]);
if (!(self.loginDic == nil)) {
self.integer = [[self.loginDic objectForKey:#"ABC"] count];
if ([[self.loginDic objectForKey:#"status"] isEqualToString:#"OK"] && (!(self.integer == 0))) {
self.ID1 = [[NSMutableArray alloc]init];
self.ID2 = [[NSMutableArray alloc]init];
self.ID3 = [[NSMutableArray alloc]init];
self.ID4 = [[NSMutableArray alloc]init];
self.ID5 = [[NSMutableArray alloc]init];
for (int i=0; i<self.integer; i++) {
[self.ID1 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID1"]];
[self.ID2 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID2"]];
[self.ID3 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID3"]];
[self.ID4 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID4"]];
[self.ID5 addObject:[[[self.loginDic objectForKey:#"ABC"] objectAtIndex:i] objectForKey:#"ID5"]];
}
NSLog(#"%#", self.ID1);
NSLog(#"%#", self.ID2);
} else {
}
} else {
}
} else {
}
}];
[self.dataTask resume];
}
I'm getting data, but I'm getting loginDic = null.
after you get AB , its array of Dictionary
you can easily use this valueForKeyPath like:
NSArray * AB = #[#{
#"ID1":#"response",
#"ID2":#"response",
#"ID3":#"response",
#"ID4":#"response",
#"ID5":#"response",
},#{
#"ID1":#"response",
#"ID2":#"response",
#"ID3":#"response",
#"ID4":#"response",
#"ID5":#"response"
}];
NSArray * ID1 = [AB valueForKeyPath:#"ID1"];
NSArray * ID2 = [AB valueForKeyPath:#"ID2"];
How to receive two JSON objects at a time?
The JSON you show is indeed two valid JSON encodings concatenated. If your server is doing this and there is nothing you can do to fix that then you can try to fix it yourself:
Any occurrence of ][, }{, ]{ or }[ with any amount of white space between the two characters is the end of one JSON encoding and the start of the next. Construct an NSRegularExpression to find these sequences and replace them with the same close/open bracket/brace combination but with a comma (,) in between them.
Add a single [ at the start and a single ] at the end.
These two steps will converted your concatenated JSON encodings into a JSON array of the individual encodings. Now parse and process as usual remembering you first need to index into the outermost array to access the particular JSON response before your index into the response to access the elements you need.
HTH

ABAddressBookCopyArrayOfAllPeople Not returning any People

I am starting to work with the ABAddress Book and using a very simple starting point... I want to get all the entries in my address book and put it into an array. It keeps showing 0 elements.
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
Doesn't the ABAddressBookCopyArrayOfAllPeople actually get all people from your contact list or did I misunderstand something.
NOTE TO ADMIN's My question was a Objective C related and not for SWIFT so this answer doesn't apply. In the recommended answer it explains why the OP's code migration from Objective C to Swift is flawed and doesn't work. My question is not. I am trying to understand why when I install this on my iPhone, which has hundreds of contacts allContacts has no items. I was trying to understand the correct way to put all my contacts into an array. Basically because of business need I am doing my own contact picker because I don't want to use Apple's built in one.
First of all you are trying to use deprecated apis. This may be why ABAddressBookCreateWithOptions doesn't work.
However, my recommendation based on your edit (where you say that you want to build your own UI) is to use the Contacts framework.
See this github gist:
#import <Contacts/Contacts.h>
#implementation ContactsScan
- (void) contactScan
{
if ([CNContactStore class]) {
//ios9 or later
CNEntityType entityType = CNEntityTypeContacts;
if( [CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined)
{
CNContactStore * contactStore = [[CNContactStore alloc] init];
[contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) {
if(granted){
[self getAllContact];
}
}];
}
else if( [CNContactStore authorizationStatusForEntityType:entityType]== CNAuthorizationStatusAuthorized)
{
[self getAllContact];
}
}
}
-(void)getAllContact
{
if([CNContactStore class])
{
//iOS 9 or later
NSError* contactError;
CNContactStore* addressBook = [[CNContactStore alloc]init];
[addressBook containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers: #[addressBook.defaultContainerIdentifier]] error:&contactError];
NSArray * keysToFetch =#[CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPostalAddressesKey];
CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
BOOL success = [addressBook enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop){
[self parseContactWithContact:contact];
}];
}
}
- (void)parseContactWithContact :(CNContact* )contact
{
NSString * firstName = contact.givenName;
NSString * lastName = contact.familyName;
NSString * phone = [[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"];
NSString * email = [contact.emailAddresses valueForKey:#"value"];
NSArray * addrArr = [self parseAddressWithContac:contact];
}
- (NSMutableArray *)parseAddressWithContac: (CNContact *)contact
{
NSMutableArray * addrArr = [[NSMutableArray alloc]init];
CNPostalAddressFormatter * formatter = [[CNPostalAddressFormatter alloc]init];
NSArray * addresses = (NSArray*)[contact.postalAddresses valueForKey:#"value"];
if (addresses.count > 0) {
for (CNPostalAddress* address in addresses) {
[addrArr addObject:[formatter stringFromPostalAddress:address]];
}
}
return addrArr;
}
#end
Note: This code was not written by me. The source can be found on github.

how to add json file in ActionRequestHandler safari extinction

I am develop a add blocker app, so i want to add json file in my ActionRequestHandler class from document directory. In ActionRequestHandler class already have code that add blockerList.json which is in main bundle
actually main problem is this if i edit in blockerList.json then its not editable because of permission because this file is in main bundle so aap don't provide on editing in any file.So i generate a new file in document directory which is editable but i cant add it in safari extention. here is my code
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
NSItemProvider *attachment;
NSString *contentOfURL;
NSString *documentsFilePath = [self grabFilePath:#"Block.json"];
NSURL *documentsURL = [NSURL fileURLWithPath:documentsFilePath];
if ([documentsFilePath length] != 0) {
NSError *error;
// NSURL *url = [NSURL URLWithString:APP_DEFAULT_BLOCKS_URL];//[[NSURL alloc] initWithString:APP_DEFAULT_BLOCKS_URL]
contentOfURL = [NSString stringWithContentsOfURL:documentsURL encoding:NSUTF8StringEncoding error:&error];
if (error)
NSLog(#"Error reading remote json file: %#", error.localizedDescription);
}
if (contentOfURL != (id)[NSNull null] && contentOfURL.length != 0) {
attachment = [[NSItemProvider alloc] initWithItem:contentOfURL typeIdentifier:#"public.json"];
} else {
NSLog(#"URL not defined or accessible - using local JSON");
attachment = [[NSItemProvider alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"blockerList" withExtension:#"json"]];
}
NSExtensionItem *item = [[NSExtensionItem alloc] init];
item.attachments = #[attachment];
[context completeRequestReturningItems:#[item] completionHandler:nil];
}
- (NSString *)grabFilePath:(NSString *)fileName {
NSString *filePath = [[NSString alloc]initWithFormat:#"Documents/%#", fileName];
NSString *documentsFilePath = [NSHomeDirectory()stringByAppendingPathComponent:filePath];
return documentsFilePath;
}

Set title property from NSarray in CSSearchableItemAttributeSet

I am trying to using CoreSpotlight API in application , I have plist file which has a several items on it for example animals' name . So I need to set title string equal to on of those object , for example if users search Lion , the line name and for example its features appears on the spotlight . Here is my code :
- (void)setupCoreSpotlightSearch
{
CSSearchableItemAttributeSet *attibuteSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(__bridge NSString *)kUTTypeImage];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"animals" withExtension:#"plist"];
NSArray *playDictionariesArray = [[NSArray alloc ] initWithContentsOfURL:url];
NSString *getNames = [NSString stringWithFormat:#"%#",playDictionariesArray];
NSLog(#"%#",getNames) ;
attibuteSet.title =getNames;
attibuteSet.contentDescription = #"blah blah ";
CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:#"app name"
domainIdentifier:#"com.compont.appname"
attributeSet:attibuteSet];
if (item) {
[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:#[item] completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Search item indexed");
}
}];
}
}
The problem is getNames returns all names !!! how can I filter it when is user is searching an specific word from animals.plist
Thanks .
EDIT [Plist Image]:
You can maintain NSArray and iterate through playDictionariesArray, creating & initialising CSSearchableItem object with that particular entry in your data source.
- (void)setupCoreSpotlightSearch
{
NSURL *url = [[NSBundle mainBundle] URLForResource:#"animals" withExtension:#"plist"];
NSArray *playDictionariesArray = [[NSArray alloc ] initWithContentsOfURL:url];
NSMutableArray * searchableItems = [[NSMutableArray alloc]init];
for(object in playDictionariesArray)
{
CSSearchableItemAttributeSet *attibuteSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(__bridge NSString *)kUTTypeImage];
attibuteSet.title =[NSString stringWithFormat:#"%#",object]; //retrive title from object and add here
//attibuteSet.contentDescription = #"blah blah "; // retrieve description from object and add here
CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:#"app name"
domainIdentifier:#"com.compont.appname"
attributeSet:attibuteSet];
[searchableItems addObject:item];
}
if (searchableItems) {
[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:searchableItems completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Search item indexed");
}
}];
}
}
I haven't ran and tested the code.
you are not looping through each key. Use the code provided in this question.
CoreSpotlight indexing
Try it on a device that supports indexing.
NOT iPhone 4/4s or iPad.

BAD_ACCESS when calling CSSearchableIndex indexSearchableItems

I am trying to implement the CoreSpotlight API in my app but can't seem to figure out why I am getting a BAD_ACCESS exception with my implementation:
CSSearchableItemAttributeSet * attributeSet = [CSSearchableItemAttributeSet new];
attributeSet.title = route.Options.name;
attributeSet.keywords = [route.Options.name componentsSeparatedByString:#" "];
UIImage *image = [UIImage imageNamed:#"pin_busstop.png"];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
attributeSet.thumbnailData = imageData;
CSSearchableItem * item = [[CSSearchableItem alloc] initWithUniqueIdentifier:route.ObjectID domainIdentifier:#"com.whatever.itsmyappsname.loadwithroute" attributeSet:attributeSet];
[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:[NSArray arrayWithObject:item] completionHandler:^(NSError * _Nullable error) {
NSLog(#"It worked");
}];
Looking at the call stack for the exception, I can see that it occurs on the CSSearchableIndex indexSearchableItems: completionHandler: call. However I can step past that call without the exception triggering, maybe it has to do with the completion handler, however it happens regardless of if I have one or not. I have CoreSpotlight/CoreSpotlight.h and MobileCoreServices/MobileCoreServices.h imported both in my .h file and in the target.
You're (I'm) creating the CSSearchableItemAttributeSet object incorrectly. Instead of:
CSSearchableItemAttributeSet * attributeSet = [CSSearchableItemAttributeSet new];
Use:
CSSearchableItemAttributeSet * attributeSet = [[CSSearchableItemAttributeSet alloc]
initWithItemContentType:(NSString *)kUTTypeImage];

Resources