How to add an NSEvent to a Property List? - objective-c

I'd like to encode an NSEvent using NSPropertyListSerialization, but NSPropertyListSerialization only accepts NSData, NSString, NSArray, NSDictionary, NSDate, and NSNumber objects.
Is there a recommended way to convert an NSEvent to a NSPropertyListSerialization-capable NSDictionary (and to restore an NSEvent from such an NSDictionary)?

In this situation you need to handle saving and restoring the object yourself. Or rather, the pieces of the object you're interested in, either by putting each value in an NSDictionary or storing them separately and using the values to create a new object when your class is decoded.
This situation is a little weird since you usually don't create or store NSEvent objects. If you're doing something like storing the last touch coordinate, consider using an CGPoint instead. Not only will you reduce your memory footprint by a small amount, but you can then use an NSValue to serialize the point.

Related

XPC method not invoked with NSArray of NSValues as parameter

I have an XPC service compiled 32-bit for OS-X. One of it's methods takes a single argument as a parameter, and calls a given block back on the main process.
This block takes 3 NSStrings and an NSArray that's supposed to contain NSValues solely. Each NSValue object holds an NSRect.
For some reason, the given block is not being called when the NSArray is not nil.
If instead of holding NSValues I let the array hold NSStrings, the block is being called correctly.
I'm not sure how to approach this, as there is no apparent reason for this to happen. According to the apple documentation, NSValue does conform to NSSecureCoding.
I even tried whitelisting the NSValue class (this shouldn't really be needed) using:
NSSet *readerSelectionClasses =
[NSSet setWithObjects:[NSArray class], [NSValue class], nil];
[newConnection.exportedInterface setClasses:readerSelectionClasses forSelector:#selector(MyMethod:WithReply:) argumentIndex:3 ofReply:YES];
This doesn't seem change anything.
Any idea how to pass the NSArray? I guess I could format all NSRects to NSStrings, and pass an array of NSStrings, which I know works, but this would lead to a performance decrease I would rather avoid.

How to have NSData in an object that will be converted with NSJSONSerialization?

I have a NSMutableArray with custom objects. The objects inside have a NSData field. I want to transport them to my web service using JSON format but I don't really know how to do it with NSJSONSerialization as it doesn't support NSData. Can you tell me if it's possible and provide me with some sample code or some other library that can handle this?
No. As the NSJSONSerialization documentation makes clear:
An object that may be converted to JSON must have the following properties:
The top level object is an NSArray or NSDictionary.
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
All dictionary keys are instances of NSString.
Numbers are not NaN or infinity.
NSData obviously doesn't have those properties.
So likely what you'll want to do is encode it as a Base64 string or some other form you consider acceptable (there are plenty of options other than Base64, but it's the one that immediately comes to mind). You might also be able to get by with just converting it to a string (depending on what the data is) that uses the appropriate escape codes and so on, though you should make sure that won't result in any encoding issues.
Anyway, the answer's no. Find a way to encode it as an NSString or something else NSJSONSerialization can work with.

Objective-C – Core Data entity to hold UILocalNotifications

I want to be able to store a representation of UILocalNotifications in Core Data. So for my needs I need to save the fireDate of the UILocalNotification which should be easy as Core Data has support for NSDate. I also want to save a repeat interval for the UILocalNotification in the class reference it says that the repeatInterval type is NSCalendarUnit.
So how would I go about saving the repeatInterval?
According to the docs NSCalendarUnit is a typedef for NSUInteger. So in CoreData you would store that as a Integer 32 type. In your code you can access those properties as NSNumbers.
Use -[NSInteger unsignedIntegerValue] to get the original NSUInteger value.
From what I understand of the documentation, the NSCalendarUnit is just a NSUInteger, so you could store it as a NSNumber, right?

NSArray property: copy or retain?

According to this: NSString property: copy or retain?
For NSString/NSMutableString, copy is recommended.
How about NSArray/NSMutableArray?
Since you're asking about NSArray (rather than NSMutableArray), you should use copy. NSArray is immutable, so you don't expect a property of that type to change. But NSMutableArray is a subclass of NSArray, so it's perfectly valid for someone to pass in a NSMutableArray. If you just retain that object, then it may change right under your nose. If you copy rather than retain, then the object won't change.
However, you should be aware that when you copy a container like NSArray, you're copying the container only and not its contents. If the array contains mutable objects, the contents of those objects may change even though the array itself is immutable.
choose copy, unless you have a very specific reason not to, as well as all the supporting code/interface to back that up.
i detailed the rationale and several implications here:
NSMutableString as retain/copy
that example is based on NSStrings, but the same applies for NSArrays.
If it is a problem when the underlying data changes, use copy. In fact, this is what you want most of the time, as changing data behind someone's back is a good source for bugs.
Note that copy will essentially just be a retain for an NSArray. Only when you throw an NSMutableArray in, there is more work involved.
From the link you included, it pretty much comes down to this: NSString property: copy or retain?
If you want to make sure the value of the object won't change during execution, you use the copy attribute, otherwise retain will be fine. Generally, retain will be ok for NSMutableArrays and NSArrays (as well as many other objects) as you are (usually) more interested in the object then in the value it contains. In case of an NSString you are always interested in the value, so you copy it to make sure it won't change.
#jlehr:
It depends if the developer is interested in the actual value or not. Whenever interested in the actual value, use copy (since you don't want the value to change during execution), otherwise retain is fine. From Apple's docs:
It is common practice in Objective-C code to copy value objects—objects that represent attributes. C-type variables can usually be substituted for value objects, but value objects have the advantage of encapsulating convenient utilities for common manipulations. For example, NSString objects are used instead of character pointers because they encapsulate encoding and storage.
Also from Apple's docs, on the topic of value objects:
A value object is in essence an object-oriented wrapper for a simple data element such as a string, number, or date. The common value classes in Cocoa are NSString, NSDate, and NSNumber. Value objects are often attributes of other custom objects you create.

NSUserDefaultsProblem

I have a simple problem:
I add an object to an NSArray, then I add an object to it then I use the NSUserDefaults way to save the array, but it doesn't work, I mean the array isn't saved and the console sends me this messange:
2011-03-21 23:09:53.994 Project[10490:207] * -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
""
)' of class '__NSArrayM'.
does anybody know how can I fix this.
NSUserDefaults only allows you to save basic lightweight objects; for example NSString, NSNumber and NSData. If you want to add another class, you'll have to shoehorn it into an NSData object beforehand. This is pretty simple, usually just a call to [NSKeyedArchiver archivedDataWithRootObject:array];. Note that the objects in the array must implement the NSCoding protocol, which you'll have to add to any of your own custom classes if that's what you want to save.
Also keep in mind NSUserDefaults is meant for lightweight preferences, not application data. If you have a large array of objects, you might be better served by archiving it to its own file or using Core Data (if you feel comfortable using something a little more advanced).
The only types you can save in NSUserDefaults are property list types: NSString, NSDate, NSArray, NSDictionary, NSNumber, NSData. You're probably trying to save an array of objects that aren't one of these types.