I don’t see any change. When f.child(“test”) exists then child(“thisisafile.txt”) will return a non-nil FolderItem and you can check whether the file exists (and create it if it doesn’t). If on the other hand f.child(“test”) does not exist then Child(“thisisafile.txt”) will return nil as it isn’t a valid FolderItem. But that’s just how it always has been. R2 hasn’t changed anything in this respect.
For this reason I always check for a FolderItem being nil before doing anything else with it. And I have written a method EnsureFolderExists, years ago, that will create an entire hierarchy of subfolders if necessary. In this case I would call EnsureFolderExists to make sure there is a “test” folder before creating a FolderItem for its child (that may or may not exist but the FolderItem is guaranteed to be non-nil).
But what good is chaining a bunch of .Child together and then getting .Exists = False if you don’t know which part of the path is invalid?
If anything other than the last item doesn’t exist, then you won’t be able to create something at that path.
I suppose if you were using that technique just to check if a path existed at all, and you didn’t care about why, then it would break that code, but I think that fixing the bug/inconsistency is the correct move by Xojo.
This is irrelevant, because as explained above, if you chain this way and go past a non-existent folder you’ll likely crash with a NilObjectException before you have to worry about which part of the path exists.
Unfortunately you have to check each folder level going down when creating the subfolders eg.
dim f as FolderItem = SpecialFolder.ApplicationData
f = f.Child("MyApp")
If Not f.Exists Then f.CreateFolder
f = f.Child("FolderA")
If Not f.Exists Then f.CreateFolder
f = f.Child("FolderB")
If Not f.Exists Then f.CreateFolder
Exception err as IOException
// Handle cases where a folder can't be created for some reason
This is intentional by design so not a bug. If you really want to create a full valid path without having to write that out each time then you could make your own re-usable global method like CreatePathToFolderItem(path as String) as FolderItem which could step through a given path, creating missing folders as it goes before returning a final valid folderitem.
Behaving consistently between platforms is important, so something needed to change. The “right” change would have been to make Windows and Linux behave like the Mac, since it would disrupt less code and behave more predictably. I am assuming making them behave that way was not possible, so given the options, making Mac conform to Windows and Linux is the right call. It may be a dumb design, but consistent is better.
My view on the “Xojo ‘simple’ way of use design” would be, Child() should always return some FolderItem object for all platforms and such object set a lot a flags describing its state.
.Exists():
True only if a valid path and such path resolves to something that really exists
False otherwise
.ValidPath():
False for example for
C:\whatever\l:\colon? // invalid
C:\thisExists\notExists\notExists // Has intermediate non-existent subfolders
True for C:\thisExists or C:\thisExists\dontExistYet
Etc.
Nil should be only the last case, probably memory related where your system is completely unstable at such point.
A new .ChildOrNil() should be introduced for those wanting such Nil behavior for invalid childs.
I don’t understand because it seems like some people are expecting Child to behave in some new way. The way that’s documented, the Child of an Exists=false, should be nil. I swear it always had been and if it suddenly isn’t that’s a regression.
Can someone explain what the complaint is?
I’m a little lost, because the only public ticket here is the one about the Constructor path not operating as it was documented and should have been. The change note from the private ticket suggests Child had some kind of regression that has been fixed.
I don’t see how either operating as documented would break code.
Var f as Folderitem
f = SpecialFolder.Desktop
If f.child("doesNotExist").Exists = False Then
Break
End
If f.child("doesNotExist").child("doesNotExist").Exists = False Then
Break
End
they both work in Xojo2026r1.2 but the second now shows an Exception with 2026r2, so it will break OP’s code.
No you’ve got it right. Mac was behaving differently from the documentation, so that got fixed. My complaint is that the documented behavior is unintuitive. If you go back to my comment MAJOR BUG in R2 that needs a fix asap - #16 by Thom_McGrath I posted three lines that all use the same feature, but behaves in 3 different ways. The Mac behavior made more sense.
I don’t think there is a bug that needs to be fixed. It’s behaving as documented, so… fine.
The first one is non-nil so that you can use the FolderItem object to create it.
The second one is nil because .Child returns a nil object due to the parent not existing.
The third one throws an exception because you are trying to call a method on a nil object.
It would allow such “desired” construct to work as
If Not f.child("doesNotExist").child("doesNotExist").Exists Then
// there's nothing like that in that final path or the path is invalid
End
One current hack is
Var fExists As Boolean // Store the existence flag tested here
Try
fExists = f.Child("doesNotExist").Child("doesNotExist").Exists
Catch NilObjectException
fExists = False
End
Trust me, I understand why it behaves this way. I’m saying it shouldn’t behave this way. There is no good reason why Child should return nil when the parent does not exist. I’ve heard it called an invalid path, but there’s nothing invalid about it. Just like String.FromArray(Array("", "home", "user", "documents", "stuff"), "/") would give you a string to a valid path - as in it does not contain illegal characters and its length is not too long - there is no good reason why I shouldn’t be able to get a FolderItem to the same path regardless of its existence at any level.
As I’ve mentioned, my best guess is this behavior comes from the Windows system-level calls behaving this way, so the other platforms have to suffer accordingly. Lowest common denominator and all that. But if I’m wrong and this is a Xojo-imposed limitation… sheesh that was a bad one.
I should get an exception for this because the FolderItem is attempting to point to location that can not ever exist.
Var File As New FolderItem("You Cannot Use < In File Names On Windows.txt", FolderItem.PathTypes.Native)
I should not get an exception for this because the FolderItem is attempting to point to a location that can exist, but does not exist.
Var File As New FolderItem("C:\Users\User\Documents\My App Stuff\Settings.txt", FolderItem.PathTypes.Native)
That’s the logical behavior. But not the way it behaves.
Like I’ve said over and over, I understand the mechanics, and the fix was good in the sense that it makes the Mac behave as documented. I agree that they should be consistent. I disagree with the documented behavior.