I am trying to make google drive file managing app in iOS. I am stuck because I want to search all files using any keyword and it should be display files and folder.Get all files and folder using this code.But if you search somthing, search only current file. Can you suggest me how to get subfiles and folder because it is display only single level not others.
-(void)getGDriveFilesAndFolders
{
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
if ([self.strPath length] == 0)
{
query.q = #"'root' in parents";
}else{
NSString *queryString = [NSString stringWithFormat:#"'%#' in parents",self.strPath];
query.q=queryString;
}
[GoogleDriveViewController.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,GTLDriveFileList *files,NSError *error)
{
if (error == nil)
{
[marrFiles removeAllObjects];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
for(int i = 0; i < [files items].count; i++)
{
GTLDriveFile *driveFile = (GTLDriveFile*)[files itemAtIndex:i];
if([driveFile.mimeType isEqualToString:#"application/vnd.google-apps.folder"])
{
if([driveFile.explicitlyTrashed intValue]!=1)
{
NSString *fileName = driveFile.title;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:fileName forKey:[NSString stringWithFormat:#"Folder"]];
[dict setValue:driveFile.identifier forKey:#"objectId"];
[marrFiles addObject:dict];
}
}
else{
if([driveFile.explicitlyTrashed intValue] != 1)
{
NSString *fileName = driveFile.title;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:fileName forKey:[NSString stringWithFormat:#"File"]];
long long int sizeData = [driveFile.fileSize intValue];
NSString *stringSize = [FileSizeClass stringSizeForFileWithBytes:[NSNumber numberWithLongLong:sizeData]];
GTLDateTime *modificationDate = (GTLDateTime*)driveFile.modifiedDate;
NSDate *date = [modificationDate date];
NSString *dateString = [dateFormatter stringFromDate:date];
dateString = [dateString createdTimeString];
NSString *stringInfo = [NSString stringWithFormat:#"%# %#",stringSize,dateString];
[dict setValue:stringInfo forKey:[NSString stringWithFormat:#"Size"]];
[dict setValue:driveFile.identifier forKey:#"objectId"];
[dict setValue:driveFile.downloadUrl forKey:#"downloadUrl"];
[dict setValue:driveFile.fileSize forKey:#"FileSize"];
if(driveFile.webContentLink)
{
[dict setValue:driveFile.webContentLink forKey:#"webContentLink"];
}
[marrFiles addObject:dict];
}
}
}
[tblGoogleDrive reloadData];
} else {
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"Message",nil) message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alertView show];
}
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}];
}
Using a search query like 'folder id' in parents only searches that folder's direct children, not within sub-folders. There is no built-in way to search sub-folders, but you may be able to create a compound query where you search through each sub-folder explicitly, like 'folder' in parents or 'sub-folder1' in parents ...
Related
I am using the code below to retrieve data from Url via PHP file, the tableview controller will start the Activity Indicator. What I am trying to do is to stop the indicator As soon as there are no data has been loaded to the tableview.
Her is the code;
NSString *urlString = [NSString stringWithFormat:#"http:/MyWebSite/ChoseMyLike.php?userName=%#", myString];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!data) {
NSLog(#"connection error: %#", error);
return;
}
NSError *parseError;
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
if (!json) {
NSLog(#"JSON Parsing error: %#", parseError);
NSLog(#"data = %#", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
return;
}
NSMutableArray *results = [[NSMutableArray alloc]init];
for (int i = 0; i < json.count; i++) {
NSString *cQasidaName = json[i][#"qasidaName"];
NSString *cQasidaShaerName = json[i][#"qasidaShaerName"];
NSString *cQasidaBody = json[i][#"qasidaBody"];
NSString *cQasidaDate = json[i][#"myDate"];
NSString *cQasidaTime = json[i][#"myTime"];
NSString *cQasidaRate = json[i][#"myRate"];
NSString *cQasidaId = json[i][#"qasidaId"];
NSString *cQasidaUserName = json[i][#"userName"];
NSString *cTheUserId = json[i][#"theUserId"];
NSString *cTheUserNameArabic = json[i][#"userNameArabic"];
[results addObject:[[ListOfObjects alloc] initWithQasidaName: (NSString *) cQasidaName andQasidaShaerName: (NSString *) cQasidaShaerName andQasidaBody: (NSString *) cQasidaBody andQasidaDate: (NSString *) cQasidaDate andQasidaTime: (NSString *) cQasidaTime andQasidaRate: (NSString *)cQasidaRate andQasidaId:cQasidaId andQasidaUserName:cQasidaUserName andTheUserId:cTheUserId andTheUserNameArabic:cTheUserNameArabic]];
}
dispatch_async(dispatch_get_main_queue(), ^{
self.listArray = results;
[self.tableView reloadData];
[spinner stopAnimating];
});
}];
[task resume];
}
At the moment the indicator is not stopping. What do I need to do?
Thanks
Simply call [spinner stopAnimating]; for all return paths:
if (!data) {
NSLog(#"connection error: %#", error);
[spinner stopAnimating];
return;
}
and
if (!json) {
NSLog(#"JSON Parsing error: %#", parseError);
NSLog(#"data = %#", [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding]);
[spinner stopAnimating];
return;
}
Note: it's much easier to have a single return statement and then you can always call [spinner stopAnimating]; at the end of the method... consider restructuring your code.
I have a working code, but now find the need to import & save two different Sqlite files via email "Open in" option, I tried using UIAlertView to create to different save file paths but it only seems to work with one way
- (void)handleOpenURL:(NSURL *)urlx {
NSData *dbimport = [[NSData alloc] initWithContentsOfURL:urlx];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:dbimport forKey:#"import"];
[defaults synchronize];
NSLog(#"import saved");
databaseName = #"svrStoreData2.sql";
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSError *writeError = nil;
NSString *filePathx = [documentsPath stringByAppendingPathComponent:databaseName]; [dbimport writeToFile:filePathx atomically:YES];
if (writeError)
{
NSLog(#"Error writing file: %#", writeError);
}
}
Both file have specific file names so was wonder if I could use "if equal to string" & use an if statement after I have synchronised NSUserDefaults to give two file path save options
Thanks for any help in advance
This was my UIALertView try
UIAlertView *alertdata = [[UIAlertView alloc]
initWithTitle:#"What type of data do you want to import?"
message:#"Choose data type"
delegate:self
cancelButtonTitle:#"Import RM Name Data"
otherButtonTitles:#"Import Store Visit Data", nil];
NSInteger *buttonIndex = NULL;
NSLog(#"Button Index =%ld",(long)buttonIndex);
if (buttonIndex == 0)
{
}
else if (buttonIndex == 1)
{
databaseExportName = #"export.sql";
NSArray *pathssqlite3 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *pathssqliteDir2 = [pathssqlite3 objectAtIndex:0];
filePathsqlite3 = [pathssqliteDir2 stringByAppendingPathComponent:databaseExportName];
NSData *dbimport = [[NSData alloc] initWithContentsOfURL:urlx];
NSMutableData *dbimport = [[NSMutableData alloc] initWithContentsOfURL:urlx];
NSError *writeError = nil;
[dbimport writeToFile:filePathsqlite3 atomically:YES];
if (writeError)
{
NSLog(#"Error writing file: %#", writeError);
} } [alertdata show];
Still trying to resolve, was hoping this would work, but still cannot crack it
`- (void)handleOpenURL:(NSURL *)urlx {
NSData *dbimport = [[NSData alloc] initWithContentsOfURL:urlx];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:dbimport forKey:#"import"];
[defaults synchronize];
NSLog(#"import saved");
if([[urlx absoluteString] isEqualToString:#"svrStoreData2.sql"])
{
NSLog(#"If statement called");
//
databaseName = #"svrStoreData2.sql";
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSError *writeError = nil;
NSString *filePathx = [documentsPath stringByAppendingPathComponent:databaseName];
[dbimport writeToFile:filePathx atomically:YES];
if (writeError)
{
NSLog(#"Error writing file: %#", writeError);
}
//
else {
databaseExportName = #"export.sql";
NSString *documentsPathy = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSError *writeError = nil;
NSString *filePathy = [documentsPathy stringByAppendingPathComponent:databaseExportName];
[dbimport writeToFile:filePathy atomically:YES];
if (writeError)
{
NSLog(#"Error writing file: %#", writeError);
}
NSLog(#"If statement Not called");
}
}
}
`
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex(NSInteger)buttonIndex {
if ([alertView tag] == 14)
{
if (buttonIndex == 1)
{
[self reviewSave];
}
}
if ([alertView tag] == 11) {
if (buttonIndex == 1)
{
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [defaultsDictionary allKeys]) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];}
}
}
Solved the problem, I had another UIAlert, so by adding Tags sorted it
I am using this line of code; my array contains name, email and phone no. This code only sorts namewise, but I want email and phone no with name. How can I do this that my array separeNamesByLetters contains email and phone with name?
NSMutableSet *firstCharacters = [NSMutableSet setWithCapacity:0];
for( NSString*string in [ tableDataArray valueForKey:#"name"] ){
[firstCharacters addObject:[[string substringToIndex:1] uppercaseString]];
}
NSArray *allLetters = [[firstCharacters allObjects] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
int indexLetter = 0;
separeNamesByLetters = [NSMutableArray new];
for (NSString *letter in allLetters) {
NSMutableDictionary*userBegeinsWith = [NSMutableDictionary new];
[userBegeinsWith setObject:letter forKey:#"letter" ];
NSMutableArray *groupNameByLetters = [NSMutableArray new];
NSString *compareLetter1 = [NSString stringWithFormat:#"%#", allLetters[indexLetter]];
for (NSString*friendName in[ tableDataArray valueForKey:#"name"]) {
NSString *compareLetter2 = [[friendName substringToIndex:1] uppercaseString];
if ( [compareLetter1 isEqualToString:compareLetter2] ) {
[groupNameByLetters addObject:friendName];
}
}
indexLetter++;
[userBegeinsWith setObject:groupNameByLetters forKey:#"list"];
[separeNamesByLetters addObject: userBegeinsWith];
}
NSLog(#"%#", separeNamesByLetters);
}
Have you considered using NSSortDescriptors? See the following example:
NSMutableArray *array = [NSMutableArray new];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:#"Doe, John", #"name", #"3361231234", #"phone", #"johndoe#email.com", #"email", nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"Doe, Jane", #"name", #"9191234532", #"phone", #"janedoe#email.com", #"email", nil];
[array addObject:dict];
NSSortDescriptor *nameDescriptor =
[[NSSortDescriptor alloc]
initWithKey:#"name"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *phoneDescriptor =
[[NSSortDescriptor alloc]
initWithKey:#"phone"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *emailDescriptor =
[[NSSortDescriptor alloc]
initWithKey:#"email"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray * descriptors = [NSArray arrayWithObjects:nameDescriptor, phoneDescriptor, emailDescriptor, nil];
NSArray * sortedArray = [array sortedArrayUsingDescriptors:descriptors];
Let me know if this helps.
When I do this, I create a new NSArray of NSDictionaries. The NSDictionary has two properties: sectionTitle and records. The sectionTitle holds the first-letter of the field you are searching on. The records contain the actual objects that begin with that sectionTitle.
Add this sectionTitle method to your model class. I usually do this in an Extension to the actual model class.
- (NSString *)sectionTitle:(NSString*)sortByProperty {
NSString *propertyValue;
if ([sortByProperty isEqualToString:#"name"]) {
if (self.name == nil) return #"";
propertyValue = self.name;
} else if ([sortByProperty isEqualToString:#"email"]) {
if (self.email == nil) return #"";
propertyValue = self.phone;
} else if ([sortByProperty isEqualToString:#"phone"]) {
if (self.phone == nil) return #"";
propertyValue = phone
}
NSString *tmp;
if ([propertyValue length] > 0) {
tmp = [propertyValue substringToIndex:1];
} else {
return #"";
}
return tmp;
}
This should be quicker than iterating through your array each time you refresh your tableView.
Next, iterate through these sectionTitles, filter your array, and add the filtered results to the records attribute of the dictionary:
- (NSMutableArray*)sortedArrayForUITableView:(NSMutableArray *)tableDataArray sortBy:(NSString*)sortByProperty {
NSArray *tmp = [tableDataArray valueForKeyPath:#"#distinctUnionOfObjects.sectionTitle"];
NSArray *allLetters = [NSMutableArray arrayWithArray:[tmp sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES]]]];
NSMutableArray *tree = [NSMutableArray new];
for (NSString *sectionTitle in allLetters) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.sectionTitle == %#", sectionTitle];
NSMutableArray *tmpArray = [NSMutableArray arrayWithArray:[tableDataArray filteredArrayUsingPredicate:predicate]];
NSArray *sortedArray = [tmpArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:sortByProperty ascending:YES]]];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:sectionTitle, #"sectionTitle", sortedArray, #"records", nil];
[tree addObject:dict];
}
return tree;
}
You will need to implement several UITableViewDataSource and UITableViewDelegate methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.tree count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *dict = [NSDictionary dictionaryWithDictionary:[self.tree objectAtIndex:section]];
NSArray *tmp = [NSArray arrayWithArray:[dict objectForKey:#"records"]];
return [tmp count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSDictionary *dict = [NSDictionary dictionaryWithDictionary:[self.tree objectAtIndex:section]];
return [dict objectForKey:#"sectionTitle"];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.allLetters;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;
}
Lastly, you will build your cell in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. Hope that helps.
Im trying to carry over a block variable and put it in my convenience initializer but the variable returns null, can someone show me the right way of doing it, Thanks, also please check if I have done my NSComparison Result correctly, here's the code,
- (void) retrieveData
{
NSURL *url = [NSURL URLWithString:jsonFile];
NSData *data = [NSData dataWithContentsOfURL:url];
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
_salesArray = [[NSMutableArray alloc]init];
for (int i = 0; i < _jsonArray.count; i++) {
NSString *sID = [[_jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString *sName = [[_jsonArray objectAtIndex:i] objectForKey:#"name"];
NSString *sAddress = [[_jsonArray objectAtIndex:i] objectForKey:#"address"];
NSString *sPostcode = [[_jsonArray objectAtIndex:i] objectForKey:#"postcode"];
__block NSString *distance;
CLGeocoder *geocoder = [[CLGeocoder alloc]init];
[geocoder geocodeAddressString:sPostcode completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && placemarks.count > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocation *myLocation = self.manager.location;
CLLocationDistance miles = [location distanceFromLocation:myLocation];
//this is the variable i want in my convenience init.
distance = [NSString stringWithFormat:#"%.1f m", (miles/1609.344)];
}
}];
[_salesArray addObject:[[sales alloc] initWithSales:sID andName:sName andAddress:sAddress andPostcode:distance]];
}
[_salesArray sortUsingComparator:
^NSComparisonResult(id obj1, id obj2){
sales *p1 = (sales *)obj1;
sales *p2 = (sales *)obj2;
if (p1.postcode > p2.postcode) {
return (NSComparisonResult)NSOrderedDescending;
}
if (p1.postcode < p2.postcode) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}
];
[self.tableView reloadData];
}
Thanks in advance to anyone that can help, this happens to be the last part of my app until completion :)
-[CLGeocoder geocodeAddressString:completionHandler:] runs the completion handler asynchronously and it won't run the block before the rest of that function finishes. distance doesn't "get null"; rather, it hasn't been set yet.
your block is run AFTER the function completes ... doesn't matter if the 'line of code' is after or before the block.
the solution is to have to block call a 'continuation' function:
e.g. instead of - (void) retrieveData
have - (void) beginRetrieveData, which calls the block and then have a - (void) finishRetrieveData, which is called by the block and doesn't run before the block ;)
here is how your code could look:
- (void) beginRetrieveData
{
NSURL *url = [NSURL URLWithString:jsonFile];
NSData *data = [NSData dataWithContentsOfURL:url];
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
_salesArray = [[NSMutableArray alloc]init];
for (int i = 0; i < _jsonArray.count; i++) {
NSString *sID = [[_jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString *sName = [[_jsonArray objectAtIndex:i] objectForKey:#"name"];
NSString *sAddress = [[_jsonArray objectAtIndex:i] objectForKey:#"address"];
NSString *sPostcode = [[_jsonArray objectAtIndex:i] objectForKey:#"postcode"];
CLGeocoder *geocoder = [[CLGeocoder alloc]init];
[geocoder geocodeAddressString:sPostcode completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && placemarks.count > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocation *myLocation = self.manager.location;
CLLocationDistance miles = [location distanceFromLocation:myLocation];
//this is the variable i want in my convenience init.
NSString *distance = [NSString stringWithFormat:#"%.1f m", (miles/1609.344)];
[self finishRetrieveData:distance]; //continue
}
}];
}
}
- (void) finishRetrieveData:(NSString*)distance
{
[_salesArray addObject:[[sales alloc] initWithSales:sID andName:sName andAddress:sAddress andPostcode:distance]];
}
I'm trying to store some items into a pList. Here is the array loop:
for (id obj in items)
NSLog(#"obj: %#", obj);
Output NSLog:
2013-03-27 13:00:40.072 mycode[47436:c07] obj: Red
2013-03-27 13:00:40.073 mycode[47436:c07] obj: Blue
2013-03-27 13:00:40.073 mycode[47436:c07] obj: Green
// The arrayWithObjects works. But I don't know how to (loop?) through my items for saving into the plist file...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"];
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: path]) {
NSLog(#"%#", path);
NSMutableDictionary *plist = [[NSDictionary dictionaryWithContentsOfFile:path] mutableCopy];
NSMutableArray *newArray = [[[NSMutableArray alloc] init] autorelease];
newArray = [NSArray arrayWithObjects:#"Red", #"Green", #"Blue" nil]; // <--- WORKS!
newArray = [NSArray arrayWithObjects:items, nil]; // <-- ?
[plist setObject:newArray forKey:#"Hi"];
[plist writeToFile:path atomically:YES];
[plist release];
} else {
NSLog(#"File not found");
}
[filemgr release];
Maybe this piece of code helps you.
NSMutableArray *newArray = [[[NSMutableArray alloc] init] autorelease];
NSMutableArray *targetArray = [[[NSMutableArray alloc] init] autorelease];
newArray = [NSArray arrayWithObjects:#"Red", #"Green", #"Blue" nil];
for(int i=0;i<newArray.count;i++)
{
[targetArray addObject:[newArray objectAtIndex:i]];
}
[plist setObject:targetArray forKey:#"Hi"];
[plist writeToFile:path atomically:YES];
or another method
NSMutableArray *targetArray = [[[NSMutableArray alloc] init] autorelease];
for (id obj in items)
{
[targetArray addObject:items];
}
[plist setObject:targetArray forKey:#"Hi"];
[plist writeToFile:path atomically:YES];
Hope this helps !!!