Secure coding NSArray

2016-02-14 Thread Quincey Morris
I might be late to this party, but since I just spent hours on it, I’ll 
document this for anyone who hasn’t run into it yet.

If you’re using NSSecureCoding, there’s a problem decoding NSArray objects. You 
can’t use this:

myArray = [coder decodeObjectForKey: @“myArray”];

and you can’t use this:

myArray = [coder decodeObjectOfClass: [NSArray class] forKey: 
@“myArray”];

The error message in the resulting exception won’t be very helpful, but it 
means that the class of the array elements is invalid. What you actually need 
to do is this:

myArray = [coder decodeObjectOfClasses: [NSSet setWithObjects: [NSArray 
class], [MyElementClass class], nil] forKey: @“myArray”];

Besides being obscure, this is also semantically incorrect, in that it appears 
to allow decoding of objects that are not strictly arrays of MyElementClass 
objects. (I guess this is not a security violation, since it doesn’t permit an 
attack to substitute objects of arbitrary classes, but it sure is annoying.]

Now, if you want to do this in Swift, you might be tempted to try the obvious 
translation:

let classes = Set (arrayLiteral: [… anything here… ])
let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)

but that won’t work because AnyClass isn’t Hashable. So you might try (well, I 
tried) something like this:

let classes = Set (arrayLiteral: [NSArray.self, 
MyElementClass.self])
let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)

This compiles, but it fails at run-time, with a message saying it found an 
object of class ‘NSArray’, but only objects of classes ‘NSArray’ and 
‘MyElementClass’ are allowed. (!)

The solution is to fall back to an explicit NSSet object:

let classes = NSSet (objects: NSArray.self, MyElementClass.self)
let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)

There really needs to be (radar #24646135) API to decode a NSArray and specify 
the class (or classes) of the elements. In Obj-C, something like:

myArray = [coder decodeArrayWithObjectsOfClass: [MyElementClass class] 
forKey: @“myArray”];

or in Swift:

let myArray = coder.decodeArrayWithObjectsOfClass (MyElementClass.self, 
forKey: “myArray”)

This would be particular useful in Swift, because it would give you 
compile-time checking of the types in the assignment. (There is already a 
Swift-only version of ‘decodeObjectOfClass’ that’s generic, so you get  the 
“correct” return type.)



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Swift bindings issue, Swift.Dictionary, NSMutableDictionary and NSObjectController

2016-02-14 Thread Samuel Williams
I have a .xib with a NSObjectController with it's content bound to a Swift
[String : AnyObject] variable, but get the following error:

*Cocoa Bindings: Error setting value for key path selection.startDate of
object [object class:
NSMutableDictionary] (from bound object ):
[<_TtGCSs29_NativeDictionaryStorageOwnerSSPSs9AnyObject__ 0x61423da0>
setValue:forUndefinedKey:]: this class is not key value coding-compliant
for the key startDate.*

1/ Is this reasonable?

2/ Should I prefer NSMutableDictionary in the Swift code?

Thanks.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Deleting an file that's been NSData memory mapped - safe?

2016-02-14 Thread Marcel Weiher

> On 11 Feb 2016, at 20:44, Dan Lau  wrote:
> 
> If a file has its contents mapped using NSData's
> initWithContentsOfFile + NSDataReadingMappedIfSafe,
> deleting it doesn't appear to affect reading it's mapped contents. Does
> anyone know if NSData uses mmap(2) under the hood to ensure that this sort
> of operation is valid?

[As Jens said: yes]

In fact, file data will stick around as long as you have an open file 
descriptor or a mapping.

A neat trick for temporary files that you want to make sure get cleaned up is 
to open() and unlink() immediately afterward.

The file data will be automatically deleted when your process exits.

Marcel


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Deleting an file that's been NSData memory mapped - safe?

2016-02-14 Thread dangerwillrobinsondanger



> On Feb 14, 2016, at 7:17 PM, Marcel Weiher  wrote:
> 
> 
>> On 11 Feb 2016, at 20:44, Dan Lau  wrote:
>> 
>> If a file has its contents mapped using NSData's
>> initWithContentsOfFile + NSDataReadingMappedIfSafe,
>> deleting it doesn't appear to affect reading it's mapped contents. Does
>> anyone know if NSData uses mmap(2) under the hood to ensure that this sort
>> of operation is valid?
> 
> [As Jens said: yes]
> 
> In fact, file data will stick around as long as you have an open file 
> descriptor or a mapping.
> 
> A neat trick for temporary files that you want to make sure get cleaned up is 
> to open() and unlink() immediately afterward.
> 
> The file data will be automatically deleted when your process exits.
> 
> Marcel
> 
> 
> ___
> 
> /
Would the file itself be accessible by another process before your process 
exits?
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Deleting an file that's been NSData memory mapped - safe?

2016-02-14 Thread Chris Ridd

> On 14 Feb 2016, at 11:45, dangerwillrobinsondan...@gmail.com wrote:
> 
> Would the file itself be accessible by another process before your process 
> exits?

Only if it manages to open it before it gets unlinked. After it gets unlinked, 
there’s no way to open it because there’s no longer any associated filename.

Chris
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Swift bindings issue, Swift.Dictionary, NSMutableDictionary and NSObjectController

2016-02-14 Thread Jens Alfke

> On Feb 14, 2016, at 2:06 AM, Samuel Williams  
> wrote:
> 
> 2/ Should I prefer NSMutableDictionary in the Swift code?

It looks like you’ll need to use Foundation collection classes, for properties 
that you want to bind in this way.

Remember, Swift’s native arrays and dictionaries aren’t toll-free bridged to 
NSArray and NSDictionary, so you can’t always use them interchangeably. They’re 
just copied to/from Foundation objects on demand, by the compiler. But binding 
doesn’t happen at compile time, so at runtime you end up with the 
key-value-coding implementation trying to operate on a native Swift object it 
doesn’t understand.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Swift bindings issue, Swift.Dictionary, NSMutableDictionary and NSObjectController

2016-02-14 Thread Quincey Morris
On Feb 14, 2016, at 02:06 , Samuel Williams  
wrote:
> 
> 2/ Should I prefer NSMutableDictionary in the Swift code?

Is your Swift property declared ‘dynamic’.

Also, keep in mind that the Swift type that’s bridgeable to NSDictionary is 
[NSObject, AnyObject]. Your type [String, 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Swift bindings issue, Swift.Dictionary, NSMutableDictionary and NSObjectController

2016-02-14 Thread Quincey Morris
(sorry about the previous post, hit Send early by accident)

On Feb 14, 2016, at 02:06 , Samuel Williams mailto:space.ship.travel...@gmail.com>> wrote:
> 
> 2/ Should I prefer NSMutableDictionary in the Swift code?

Is your Swift property declared ‘dynamic’?

Also, keep in mind that the Swift type that’s bridgeable to NSDictionary is 
[NSObject: AnyObject]. Your type [String: AnyObject] can be upcast to a 
bridgeable type, but things get a bit murky about what’s supposed to happen 
when.

Also, I recommend that you do *not* use a mutable dictionary as a cheap 
replacement for a class with its own properties. It may seem like a good 
shortcut, but it’s going to have limitations (perhaps unrelated to the current 
problem) when you start binding to it.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Swift bindings issue, Swift.Dictionary, NSMutableDictionary and NSObjectController

2016-02-14 Thread Samuel Williams
Yeah, the easiest solution was to not use a dictionary but use a class,
which copied the data into the dictionary.

Here is the top level sheet:

class PMSRConfigurationSheet: NSWindowController {

dynamic var metadata: [String : AnyObject] = [String : AnyObject]()


override class func keyPathsForValuesAffectingValueForKey(key: String) ->
Set {

if (key != "metadata") {

return ["metadata"]

} else {

return []

}

}


@IBOutlet var objectController: NSObjectController?


@IBAction func apply(sender: AnyObject?) {

objectController?.commitEditing()


if let window = self.window {

if let sheetParent = window.sheetParent {

sheetParent.endSheet(window, returnCode: NSModalResponseContinue)

}

}

}


@IBAction func cancel(sender: AnyObject?) {

objectController?.discardEditing()


if let window = self.window {

if let sheetParent = window.sheetParent {

sheetParent.endSheet(window, returnCode: NSModalResponseAbort)

}

}

}

}

Here is the actually subclass with some properties:

@objc(PMSRExpenseReportConfigurationSheet)

class PMSRExpenseReportConfigurationSheet: PMSRConfigurationSheet {

dynamic var startDate: NSDate? {

get {

return self.metadata["startDate"] as? NSDate

}

set(value) {

self.metadata["startDate"] = value

}

}


dynamic var endDate: NSDate? {

get {

return self.metadata["endDate"] as? NSDate

}

set(value) {

self.metadata["endDate"] = value

}

}

override init(window: NSWindow?) {

super.init(window: window)

}


required init?(coder: NSCoder) {

super.init(coder: coder)

}


init() {

self.init(windowNibName: "PMSRExpenseReportConfigurationSheet")

}


override func apply(sender: AnyObject?) {

print("Date range: \(self.startDate) -> \(self.endDate)")

super.apply(sender)

}

}

Works perfectly!
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com