If an app sets data in the UIPasteBoard of iOS, are they deep copied or shallow copied?
If you ask about - (void)setData:(NSData *)data forPasteboardType:(NSString *)pasteboardType than it is surely a Deep copy.
If you ask about strings, URL's, Colors they are also Deep copied.
Only about the Images I am preety sure that it uses the same CGImageRef, because UImage does not implement NSCopying protocol
You can test it just closing your application and see that data stays in the pasteboard.
UIPasteboard uses NSData to store the data. Hence, it is deep copy.
From the official documentation for "setData:forPasteboardType:"
"Use this method to put raw data on the pasteboard. For example, you could archive a graph of model objects and pass the resulting NSData object to a related app via a pasteboard using a custom pasteboard type. (To put objects—such as NSString, NSArray, NSDictionary, NSDate, NSNumber, UIImage, or NSURL objects—on the pasteboard, use the setValue:forPasteboardType: method.) This method writes data for the first item in the pasteboard. Calling this method replaces any items currently in the pasteboard."
Related
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.
I'm using Rest Kit with Core Data, one of the Core Data entities has an attribute 'image' that has a binary type.
I'm still in mockup stage so the image is populated with this code:
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://lorempixel.com/60/60/people"]]];
entry.image = UIImagePNGRepresentation(image);
Another tab has a collection view that uses fetchedResultsController.
After creating a new entity, if I only save the context the image works fine.
But if I push the entity to the web server using 'postObject:' the image is corrupted when it comes back from the server. I've confirmed the server receives the same string representation of the image "<2f396a2f 34414151 536b5a4a 52674142 ... 6a6e502f 32513d3d>" and stores it directly into a MySQL column of type long blob and at all points the string representation is the same.
But when the collection view is populated using a server call via RestKit the entities image is invalid. I'm think the issue is the data is being converted into the data representation of the description of the data.
Does anyone have a working example with images. The only thing I can think of is that I need to add a custom transformation, but the documentation and examples are lacking as far as how to actually implement one.
RestKit is storing the plain NSData for the image in Core Data - it has no idea what else you might want to do with it. Generally you don't want to manage images directly in Core Data or using RestKit.
Generally, store the path of the image in Core Data and the file on disk. Download them asynchronously (from the URL's which would also be in Core Data).
For uploading, you could make RestKit upload the data, but you probably actually want to file upload or convert to base64. You will need to write some code for this (which you could have RestKit pick up by using the key of the method name that returns the appropriate data). A similar process will work for mapping the data in.
RestKit data transformers are hard to make work in this situation as you are converting between data and strings and they are too general to be able to intercept accurately.
I'm just confused about when to use NSData. I'm about to get some data stored in the server (I'm just using dropbox here instead for some practice.)
What I did so far is
Made some p-list storing 2 arrays, one stores string object , and the other stores string objects of the public URL for the audio data.
When I created the NSString from the plist , I didn't use NSData object
When I created the NSAudio Player with data stored in the same project folder, I didn't use NSData object
When I created the NSAudio Player with data stored in a server, I used the NSData
I just don't understand when to use NSData object properly. I checked the app document, but it says "Data objects let simple allocated buffers" What is the allocated buffers here?
Thanks,
NSData is just a wrapper for a byte array. Anywhere that you specifically need a byte array you can either use a byte array and do all manipulations manually (accessing and manipulating the data) or you can wrap it in an NSData (or NSMutableData if you need to modify the bytes) and use Apple provided functions to easily access or modify the data.
The allocated buffer is the byte array stored inside the NSData wrapper. Say you have an audio object on disk that you want to modify one byte in the middle of. You could load that data from disk into an audio element, but then you can't modify it. If you load it's byte values from disk into an NSMutableData you can have access to the bytes directly, modify whatever you would like using simple methods provided to the NSMutableData class, then same the audio element back to disk (or load that data directly into your audio element).
The best use of an NSData object is only when you need it, just like any other class. If you specifically need the functionality to run your app, then use it. Otherwise it is likely just an added step that is not required (ex data-on-disk -> audio-element vs data-on-disk -> NSData -> audio-element).
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
I am working on an application where the user is able to draw on the screen with their finger. I am using UIBezierPath for this. I need to persist this data which is an NSArray containing multiple BezierPath objects. What is the best way to go about this? Store in coredata, store in a file using NSData? Much obliged.
Are you expecting to have to store multiple objects? Will you need to be able to fetch them based on some filter or ordering? I recommend using Core Data to save yourself a decent amount of work in packing/unpacking the data. There isn't really a reason to store it in a file.
edit:
As the other answer said, you just archive it to NSData. The UIBezierPath class adheres to the NSCoding protocol so you can do something like this to archive it:
NSData *bezierData = [NSKeyedArchiver archivedDataWithRootObject:bezierPath];
You can persist that NSData object in Core Data.
To decode the archive, assuming we have a bezierData NSData object, you can do something like:
UIBezierPath *bezierPath = [NSKeyedUnarchiver unarchiveObjectWithData:bezierData];
Archive the UIBezierPath to NSData, and store it as an attribute of type NSData in CoreData. You can have an easier API if you make it a transformable attribute.
It's pretty easy to do, especially for classes that already support archiving.
See this document for more information.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html