Using Delta in Dropbox API with iOS - objective-c

I'm using the dropbox api for iOS and have been messing with the loadDelta function. I get the whole "key" that is sent, and I get how the structure is set up (see below this code), but what I don't understand is how to download the file that is sent and how to save it to the iOS device. Does anyone have any insight on how to do this?
-(void)restClient:(DBRestClient *)client loadedDeltaEntries:(NSArray *)entries reset:(BOOL)shouldReset cursor:(NSString *)cursor hasMore:(BOOL)hasMore{
for (DBDeltaEntry *file in entries) {
if(!file.metadata.isDirectory){
NSLog(#"File: %# ", file.metadata.filename );
}else {
NSLog(#"Directory: %# ", file.metadata.filename );
}
}
}
The call sends back an array called entries. Each entry in entries is this:
#interface DBDeltaEntry : NSObject {
NSString *lowercasePath;
DBMetadata *metadata;
}
with the DBMetadata object being:
#interface DBMetadata : NSObject <NSCoding> {
BOOL thumbnailExists;
long long totalBytes;
NSDate* lastModifiedDate;
NSDate *clientMtime; // file's mtime for display purposes only
NSString* path;
BOOL isDirectory;
NSArray* contents;
NSString* hash;
NSString* humanReadableSize;
NSString* root;
NSString* icon;
NSString* rev;
long long revision; // Deprecated; will be removed in version 2. Use rev whenever possible
BOOL isDeleted;
NSString *filename;
}
What I can't figure out is how to recursively set up my offline structure or the best practice for doing so. My assumption is though, using delta, I won't need to keep a database of the files I have saved for update purposes, right?

The /delta call only tells you what has changed. It doesn't itself give you any access to the file contents. If you want to download any particular file that you heard about from /delta, you should use the path it gave you with the /files (GET) call to download the file:
https://www.dropbox.com/developers/reference/api#files-GET
(The iOS SDK makes this available as the loadFile function.)
The /delta call does save you the trouble of having to call /metadata to manually figure out what has changed and keep track of the current state, but note that the Dropbox API best practices ( https://www.dropbox.com/developers/reference/bestpractice ) do say that you shouldn't download anything until the user asks for it.

One scheme is to use a SQLite table with the following columns:
lc_path: The lowercase'd path of the file (primary key for this table)
name: The name of the file
lc_parent_path: The lowercase'd path of the parent folder
other metadata... (last modified, revision, is_dir, etc.)
So when processing an "add" /delta entry, you insert a row into the table (you might have to replace an existing row).
When processing a "delete" entry for the path /a/b/c, you need to delete all children as well, so you can do DELETE ... WHERE lc_path = "/a/b/c" and then DELETE ... WHERE lc_path LIKE "/a/b/c/%".
If you want to query the database for a list of immediate children of the folder "/a/b/c", do SELECT ... WHERE lc_parent_path = "/a/b/c"
You may have noticed that you the path is stored somewhat redundantly (lc_parent_path+name and lc_path). This probably won't be a problem. But if you find that your database is too large and that most of the space is going toward storing the path strings, there are encoding tricks you can do.

Related

Change Away Status on Nest Thermostat (Nest API)

Using the Nest API I am trying to set the nest thermostat's away status
Reading & Setting for temperature is working fine.
I have the read and write permissions correctly configured for both
thermostat temperature control and for setting thermostat away
I can read the status correctly. Does anyone with some experience of this API know how to go about setting this status?
in "FirebaseManager.h"
Firebase *newFirebase2 = [self.rootFirebase childByAppendingPath:#"structures"];
[newFirebase2 observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
// Put structures into a dictionary
NSMutableDictionary *dict = snapshot.value;
NSLog(#"\n\n\n1. Away Status = %#", [dict valueForKey:#"away"]);
NSLog(#"Dict Contents %#", dict); // <--- Reads thermostat status. A string either home or away
dict[#"away"] = #"away"; //<--- Changes status string but not a correct solution, and does not set the stat to away
//Changes status name but this is not parsed back to firebase
NSLog(#"new status = %#", [dict valueForKey:#"away"]);
}];
To update a child value
assume this structure
structures
structure_id_0
away: "home"
setting the away node to a string of away (this code is quite verbose so it's easy to follow)
Firebase *structuresRef = [self.rootFirebase childByAppendingPath:#"structures"];
//build a reference to where we want to write structures/structure_id/
Firebase *thisStructureRef = [structuresRef childByAppendingPath:#"structure_id_0"];
Firebase *awayRef = [thisStructureRef childByAppendingPath:#"away"];
[awayRef setValue:#"away"];
Now, if you want to do this for snapshots that have been retrieved via observing a node with FEventTypeChildAdded, the node name will be whatever is used in place of structure_id_0. The is the key of the key:value pair.
That can be obtained via snapshot.key.
So NSString *key = snapshot.key
Substitute the key variable in for #"structure_id_0" in the path.
Also check out Firebase Writing Data, and then the updateChildValues for another option.

get contents of data array from fwrite parameter - to print out data with objective-c

I have some code that reads this:
int SaveTemplateToFile(char* Name, FTR_DATA Template )
{
//NSLog(#"trying to save template to file");
FILE *fp;
fp = fopen( Name, "w+b");
if( fp == NULL ) return FALSE;
int Result = fwrite( Template.pData, 1, Template.dwSize, fp ) == Template.dwSize ? TRUE : FALSE;
fclose(fp);
return Result;
}
I understand that this will write out the data retrieved from Template.pData into a file named whatever is stored in the Name variable.
This is what the .tmpl's contents reads:
Task/Question:
I am simply trying to store this data into a variable so that I can send this data to my webserver database and store it in a blob file for retrieval at a later time. This will also allow me to get rid of the fwrite function which I wont need since im storing everything onto the sebserver instead of storing it locally.
I am currently finding trouble reading this data. I am getting a crash when trying to output this data array, I also present what the datatype structure looks like:
Where DGTVOID is of typedef void DGTVOID.
How can I correctly read the contents of template? I was thinking if I understood what datatype it is, then I would be able to retrieve the data correcty.
Update 1
Thanks to Paulw11 I am able access a very small portion of the data using %s instead of %# which originally lead to a crash. Here is what is being printed now, a few funky upside down question marks:
Is there a way to output the contents of this datastream from Template.pData without having to save the data onto the direction first as a file?
I think the first thing you should do is convert your buffer to an NSData instance -
NSData template = [NSData dataWithBytes:Template.pData length:Template.dwSize];
Once you have that then you can Base64 encode the data for transmission over a web request -
NSString *templateStr = [template base64EncodedStringWithOptions:0];
If you are targeting a version earlier than iOS7 then you can use the deprecated method
NSString *templateStr = [template base64Encoding];

Core Data and unique UIImage per object

I am making a simple app where the user can create severals objects which are saved with CoreData.
My problem is, I want each object to have an image linked to it. The image is brought by the iphone camera or the user personal Camera roll, so the images will have a pretty high weight (> 1MB each I think).
I read that when the weight of images is that high, the good way to handle this is to save the images in the documentsDirectory folder, and save the path to coreData. I achieved this pretty easily.
But how do I find a path name for the image to be linked to an unique object? CoreData does not really handle unique IDs, and two objects can have the same name... I searched around objectID but it's not working really good and I'm not sure it's the good way to handle this.
Do you have any idea? Is there an other simple way I am totally missing? Thank you in advance.
use coredata's objectID as identifier
id uri = [self sanitizeFilename:coreDataObject.objectID.URIRepresentation];
[NSString stringWithFormat:#"%#.png", uri];
helper sanitizeFilename:
- (NSString *)sanitizeFileNameString:(NSString *)fileName {
NSCharacterSet* illegalFileNameCharacters = [NSCharacterSet characterSetWithCharactersInString:#"/\\?%*|\"<>"];
return [[fileName componentsSeparatedByCharactersInSet:illegalFileNameCharacters] componentsJoinedByString:#""];
}
Just create an object_id number property in your CoreData model entity description and each time a new object is created increment this property by one and assign it to the object, then use a naming convention like
[NSString stringWithFormat:#"object_%d_img.png", idNumber];
And save it to NSDoctumentsDirectory.
Then in object's - (void)prepareForDeletion method delete the image.
As for how to increment the id value, create a method that will fetch an object with biggest id value - simply get all objects with sort descriptor by id desc and use it + 1 when creating a new entity.
Thanks to #Daij-Djan. I created version for Swift:
var itemObjectId:String = item.objectID.URIRepresentation().absoluteString!
var fileName = NSString(format:"%#.png", FileHelper.sanitizeFileNameString(itemObjectId)) as String
Helper for sanitize:
struct FileHelper {
static func sanitizeFileNameString(fileName:String) ->String {
let illegalFileNameCharacters:NSCharacterSet = NSCharacterSet(charactersInString: "/\\?%*|\"<>")
let components : [String] = fileName.componentsSeparatedByCharactersInSet(illegalFileNameCharacters)
let joinedString = join("", components)
return joinedString
}
}
I think you'll need to generate the unique id by your self. Since a user can have several objects. so maybe the image id could be named as such
userId-objectId-somesalt
save the value to the object's path

How i retrieve data in iOS xCode SDK?

I am using Titanium. and I want to make Titanium Module (for iOS).
every thing is working fine. But, how i retrieve data in xCode whose i send through .js file.
in .js file
var data = "Mritunjay";
var oldData = "Singh";
var data = module_tset.findData({"newData":data,"oldData":oldData});
in xCode
-(id)findData:(NSMutableArray *)args
{
NSMutableArray *ary = [[NSMutableArray alloc]initWithArray:args];
// How i retrieve "newData" Value in xCode?
}
please help me..! thanks
First you should check the documentation for this.
Also, check the example moddevguide projects on GitHub, they have very simple and straightforward examples of how to do this.
In a nutshell heres the code to extract those arguments (assuming you setup this correctly).
-(id)findData:(id)args
{
ENSURE_SINGLE_ARG(args,NSDictionary); // Standard practice
NSString *newData_Pass = [TiUtils stringValue:[args objectForKey:#"newData"]];
// Now do something with newData!
}
Thats it!

Where does the Finder obtain the "date added" of an item in a folder?

If a folder is placed in the Dock you can sort it by "date added" - this is usually the default for the Downloads folder. (Sometimes the Finder does not appear to be using the date added but the date modified, but it can find the date added.) Where is the Finder figuring this out from? The standard file metadata, i.e. as obtained by stat, getattrlist or FSGetCatInfo) does not contain it. TIA
Yep, the date added could be inferred from other structures. In fact, it resides in Spotlight metadata.
NSDate *dateAdded(NSURL *url)
{
NSDate *rslt = nil;
MDItemRef inspectedRef = nil;
inspectedRef = MDItemCreateWithURL(kCFAllocatorDefault, (CFURLRef)url);
if (inspectedRef){
CFTypeRef cfRslt = MDItemCopyAttribute(inspectedRef, (CFStringRef)#"kMDItemDateAdded");
if (cfRslt) {
rslt = (NSDate *)cfRslt;
}
}
return rslt;
}
Note: out of date now that Lion’s out.
The Finder isn’t, the Dock is. It tracks this data internally. If you remove a folder and put it back, the “date added” information is lost for existing items.
Here's a Swift 5.x version of Wojtek's answer:
public extension URL {
var dateAdded: Date? {
if let metadataItemValue = MDItemCreateWithURL(kCFAllocatorDefault, (self as CFURL)) {
return MDItemCopyAttribute(metadataItemValue, kMDItemDateAdded) as? Date
}
return nil
}
}
I've tested this back to Swift 4.x, and I think it'll compile without modification back to Swift 3.x if you need that too. Just be aware that, before Swift 5, its inferred visibility would be internal rather than public.