Objective C: Print/Log an array as usable code? - ios

I'm programmatically building an array of dictionaries with hundreds of values I'm pulling from various sources. I then plan to go in and manually change a few of them as needed. I don't want to use this pulling method in the production code, I want to just store it as a vanilla array with dictionaries. However when using NSLog it returns the array obviously, but not as code I can copy and paste. I'd hate to have to go through several hundred values and and manually convert everything to be proper objective c code.
So in short, is there any way to return my array as actual code?

One approach would be to write the final array to a plist file. Then make the plist file part of your project. No need to generate code for the array. Simply load the plist into an array at runtime.
To save the array as a plist:
[myFinalArray writeToFile:somePath atomically:YES];

Related

IOS Shortcuts: Setting (nested) dictionaries with application to modify EXIF data

I am trying to set values in a nested dictionary - similar to pythonic dict["key1"]["key2"]=value1 in Apple's my shortcut app on IOS 13. I fail even with a simple dict see attached screenshot which should add an element to the dict. The endgame is to modify EXIF metadata via the Metapho app - non-working example attached
I used ttwo approached
use a basic operation to modify dictionary
use prexisting shortcuts to modify dicitonaries as outline on the following Reddit threat Dictionary utilites.
To reproduce you need to download the attached shortcuts - and Dictionary utilties for the examples using those.
I first checked if I can modify a non-nested dict and nonnested dict.
Modifying non-nested dictionary
Using core tools I cannot add a key-value pair to a dictionary.
Minmal non-working exampleas per below.
Modifying non-nested dictionary using Dictionary tools
Minmal working example
Modifying nested dictionary using Dictionary tools
Using the same tools to modify nested dicts does not work.
Minimal non working example
Any help greatly appreciated. Asked same question on ask different
If values of a dictionary are modified the variable needs to be reset:
reset variable
Using this both nested and non-nested dicts can be modified without external tools.
Essentially this is called by value instead of call by reference. If those tools are used still their output needs to overwrite the variable in question.
Regarding modifying the underlying Exif values it is important it is important that again the output imagevariable needs to be written to new file in the photo app.
Mac

Parse, How to send array entries as multiple PFObjects, Create a new row for each array object

I'm using Parse as the backend for my app. My app will be used in the field where service will nonexistent or spotty at best so I need to store information offline. I currently save data for the user in a plist in the background (Title, location coordinates, notes, additional data). Since Parse's current iOS offline saving is fairly poor (From what I've read), I was hoping to get around it by creating an array or dictionary from the plist and upload that to Parse by giving it an array once the user is back in cell range.
As it occurs now, when I upload the array, it simply puts the entire contents of the array in a single cell in the database. Is there a way to parse the array and create a new row for each entry/object in the array?
I may have overlooked a better way to do this. If someone has a suggestion I would appreciate it!
I solved it. I iterated through the array using a for loop and added each index as a separate object.

Saving NSArray data to disk

I have an NSMutableArray that contains NSMutableDictionary's. Each dictionary has an AVAsset, an NSURL, an NSString, and two UIImages. I want to save my array to disk so that each time I close and open my app, I can load the array and convert the URLs's to NSData objects in order to play audio and use the AVAssets for some other actions. I know I can save and load my array using initWithContentsOfFile and writeToFile:atomically and this answer is pretty informative: Saving a NSArray. However, that answer was from 2009. Is there a better way of saving and loading an array these days?.
As for the answer you linked, the answer is still valid. And according to it, you cannot store it the way it mentions. This is because array must be plist format compatible in order to be saved like that. When you parse your array down to lowest element hierarchy, you have UIImage which is just an object pointer and doesn't make sense.
One practical way would be store UIImages as separate files, and store their paths as part of your NSMutableDictionary objects. Same holds true for AVAssets. Off course you need to engineer the solution to fully accomplish this goal.
One more way to store non-plist compatible objects is to use archiving and unarchiving feature. Refer to the documentation. Here, make sure that each object in the tree follows protocol NSCoding (Probably, AVAsset in your question does not conform to it, so you need a way to work around it). For an example, see this answer and search the likes of it.

Best practice to process big plists?

I'm using a plist file which contains all app my data. The file is quite big and currently I'm loading all the stuff into Arrays and Dictionaries at first launch and save them into UserDefaults so that I don't have to touch the plist again. As this takes about 10 secs (iP4) I wonder if there is an even faster (better) way to process the plist. I checked the whole startup with Instruments and going through the hundreds of entries is actually the fastest part. It takes very long to save these processed stuff into NSUserDefaults.
You might benefit from saving the plist to your own file. That way you control the reading/writing, don't have any overhead associated with NSUserDefaults, and, most importantly, can ensure the format. That is, if reading/writing is producing the slow down, then you'll have to minimize the plist file size. Likely using a plist format of NSPropertyListBinaryFormat_v1_0 will do that:
See:
+ (NSInteger) writePropertyList: (id) plist
toStream: (NSOutputStream *) stream
format: (NSPropertyListFormat)format
options: (NSPropertyListWriteOptions) opt
error: (NSError **) error
From Apple's Property List Programming Guide:
The first approach [using NSDictionary or NSArray writeToFile] is
simpler—it requires only one method invocation instead of two—but the
second approach [as above] has its advantages. It allows you to convert the
runtime property list to binary format as well as an XML property
list. When you convert a static representation of a property list
back into a graph of objects, it also lets you specify with more
flexibility whether those objects are mutable or immutable.
Several points.
NSUserDefaults is probably just a big plist, so why use it? Stick your entries into a singleton that holds the in-memory structure.
If you're doing this on first load because you want it to be mutable, put the defaults into your resource folder. When you want to load it, check if you have it in the documents folder, and if you don't ( first load), copy it from the resource bundle to the documents.
If you're using NSUserDefaults for persistence, just write out your data to your plist in applicationShouldResignActive, and at any other times where you make important changes.
Write it in a background thread, but you probably need to do some locking here.
Best practise when load and save times become to big is probably move to core data, but 1-4 should give you some more mileage before you need to do that.

Read plaintext document into NSArray in iOS?

I'm new to iOS but have plenty of experience with c++ and Python. I'm trying to figure out how to read a plaintext file I have on my computer into an NSArray in xcode. In c++ I would do this:
while(istr>>string) myArray.push_back(string);
However, I need to create a local copy to be stored on the iOS device. Is there a way I can package this data so that a local copy of JUST THE ARRAY will be stored on the device? I was thinking of maybe doing something with a JSON serialization or something.
Should I really just suck it up and do this:
NSArray myArray = [[NSArray alloc] initWithObjects: #"myInfo", nil];
I just want a more elegant way to handle this, I guess.
I think maybe you're thinking a little too C about this. In C and C++, strings are arrays of bytes. In ObjC, there's an object for that. It's called NSString, and it's probably what you should be storing plaintext in.
It even has an easy class method to help you out with this if you already have a byte array:
+(id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc
See the NSString documentation for more details.
As to storing it on the device, there are solutions that range from the simple (NSUserDefaults) to the complex (Core Data), but pretty much anything will expect plain text be in an NSString.
EDIT:
The title of this question talks about reading the string from the filesystem. First step is to get the bytes of the file into an NSData object. The easy way:
+(id)dataWithContentsOfFile:(NSString *)path
Then make a string out of the data with this initializer of NSString:
-(id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
I don't know if this can help you, anyway if you just need to store an array of data to filesystem and deserialize it back to NSArray, an easy way is to use plists.
It is a convenient way to store a small amount of data, without any kind of relationship (there is Core Data for that). The main advantage is that you can store in it NSArray, NSDictionary, NSNumber, NSString, NSDate and NSData (so any kind of binary information) and they get automatically serialized and deserialized through some simple methods.
You can write an NSArray to a file in this way:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
and deserialize it back with this:
+ (id)arrayWithContentsOfFile:(NSString *)aPath
If you just want to provide some initial data to your app, and it is for example an array of strings or something similar, you can manually add a plist to your project by going to File->New->File and choosing Resources->Property list, and fill it by hand.
You can read more at https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/PropertyLists/Introduction/Introduction.html

Resources