My flux app displays a list locations. When user clicks on a location, it becomes 'active'. There can be only one active location at a time.
Should the state of location be a property of the location itself (e.g. location.active) or should it be part of the global state, e.g. activeLocationId?
I have written several variations of the app. It became obvious that active is not a property of the item itself (location in this case), but is the property of the UI (activeLocationId).
Some benefits:
Single source of truth (You will not end up accidentally with two active locations).
It is not affected if new location list is loaded (This is regardless of wether the new list includes the active location or not).
Makes it easy to find the active location ID.
Related
Many places here on StackOverflow, this question has been asked and answered. However, I have found most of those, while technically correct, leave out some specific details that not only explain what's actually going on, but can be valuable information when trying to debug file references or build issues.
I decided to post this here per Jeff Atwood's own comments on encouraging posting your own answers where he says...
It is not merely OK to ask and answer your own question, it is explicitly encouraged [...] I do it all the time!
As such, I'm adding a detailed explanation of what exactly happens under the hood with these items hoping this knowledge can help others as it has helped me, especially in regards to clearing up the all-too-common misconception of thinking as of Xcode 9, the project tree mirrors the on-disk folders, which isn't actually the case.
A Deep-Dive Into Groups and Folder References
As mentioned above, there are lots of answers here on SO around this topic, all which explain the basic differences. However, there are some subtle details that are omitted when it comes to behaviors and understanding of what's actually going on which can lead to a frustrating experience when your project or its changes aren't working as expected. As such, I'm tossing my hat into the ring with a more thorough explanation. Hopefully this will help avoid a lot of headaches.
Now, let's get our hands dirty!
Folder References
Folder references are simpler to grasp. They are simple pointers to actual on-disk folders. Whatever's in the folder on-disk will appear in the project tree.
You identify a folder reference by its icon, which will be blue.
You can include whatever is in that folder in your application by selecting the folder reference in your project tree, then choosing which target to include it in in the inspector.
Note: You can only choose the target at the Folder Reference level, not the individual file level. It's an all-or-nothing addition.
An important side-effect is while you can bundle resources into your application from a folder reference, you CANNOT build source code from a folder reference. Source code must be in groups!
Groups
Groups on the other hand are deceivingly more complex. In their simplest explanation, they are logical-only containers in your Xcode project that you use to store and organize relative pointers to your source code files. These are stored in the Xcode project only, not on disk.
You can identify a group in your project by a yellow folder.
Each item, whether a group itself or a file-reference within the group specifies a location and how it is related to the project's structure. This can be found in the 'Identity and Type' section of the inspector.
Of note...
Groups can reference a specific folder on disk, but don't have to
File references must point to a specific file on disk.
How those references are stored depends on the value for 'Location':
If 'Location' is set to 'Absolute Path' then the reference will contain the entire on-disk path to the item.
If it's set to 'Relative to group', then its first determined what the group currently resolves to, then the references are stored relative to that value. This will propagate recursively up through the parent groups.
There's also a subtle difference in the iconography. If the group points to an actual folder, you will just see the yellow folder. If however, the group doesn't reference a specific folder (i.e. it is logical-only) you will see a small triangle in the folder's icon.
Additionally, regardless of whether the group is connected or not, you can always see what the current physical location referenced by a group or any of its children by looking at the 'Full Path' property in your inspector.
Again, it's important to note that your logical 'groups' structure has nothing to do with the physical on-disk structure. People regularly make the mistake of thinking starting with Xcode 9, that statement isn't true, but read on to know why that misconception still exists.
As mentioned, groups do not represent actual on-disk folders. They are simple logical groupings purely for code organization. However, they can point to an actual on-disk folder. You set which folder that is via the little folder button under the Location dropdown in the 'Identity and Type' section of the inspector. You can also clear that association again by pressing the little x in the circle.
Now here's the tricky part to get. When dealing with groups that aren't pointing to actual folders, their entire purpose is simply to help you as a user organize your code in a structure that makes sense to you, and for Xcode to be able to resolve the actual paths on disk to those file references.
But what if you have a group that does point to a folder? Well now an entire new set of rules comes into play. These rules are what changed in Xcode 9.
After Xcode 9, modifying a group's name may modify the on-disk name, but not necessarily. It will only do so if the group name and physical folder name match prior to the rename. If they don't, they are for all intents and purposes 'disconnected'.
For instance, say you have a group in your project called 'Virtual' that points to a folder on-disk called Literal, like so...
Group On-disk Folder
----- --------------
Virtual -> Literal
If you rename the group 'Virtual' to 'Conceptual', nothing happens on-disk.
Conceptual -> Literal
If you then rename 'Conceptual' to 'Literal' so it matches the actual folder name on disk...
Literal -> Literal
...then again rename 'Literal' to 'Changed', both the group and the folder will be updated to 'Changed'.
Changed -> Changed
Note: This has nothing to do with where the folder is on-disk. This is only pertaining to the name itself, nothing else.
Where are we going?
As for where it is on disk, there too things are more complex than they seem. If you move a group that is not currently pointing to an actual on-disk folder, nothing happens except Xcode updates how it stores your project's items' relative paths in the project file, making them relative to the updated group structure.
However if you move a group that is currently pointing to a folder--even if its name doesn't match the folder on disk (that is a critical point and an oft-source of confusion about 'corrupted' project trees)--the physical on-disk folder it points to will be moved to the new location relative to whatever group you drag it under, along with all items in that folder on disk whether referenced in your project or not!
For instance, say you have this in your project structure...
Project
GroupA -> Points to \Code\Project\GroupA
GroupB -> Points to \Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB
And you drag GroupA so it's under GroupB in your project tree tree, like so...
Project
GroupB
GroupA
Since GroupA points to a physical folder on-disk (again, remember, this has nothing to do with whether the group name and directory name match, only that the group points to an actual directory), the on-disk directory and all of its contents whether referenced or not will actually physically move to
\Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB\GroupA
Again, you are moving it to be under whatever the target group's actual on-disk path is.
Now, if GroupB doesn't actually point to a folder, but GroupA does, then the final location resolves to where GroupB resolves to on disk, which means it considers all of its parent groups to determine the location.
Most Common Scenario
The good news is that for 95% of all use-cases--really, unless you are dealing with a legacy code-base or you actively alter a new project's structure--the physical on-disk folder structure will match the project structure, and all those folder references should be set 'Relative to Group' meaning the groups are essentially mirroring the file system. That is why people think starting with Xcode 9, you are modifying the file system, but again, you are not. You're still just modifying groups and file references. It's just Xcode is making assumptions that if your groups structure mirrors the physical disk and you rename/reorder them, chances are you also want the physical disk to update, so it does it for you. It's very convenient if albeit a little misleading.
With this new knowledge, if things get out of whack and aren't working as you're expecting them to, it may be time to check your file and group references and relative locations. Make sure your folder references are actually pointing to where you are expecting them to be, especially when upgrading older projects, and you should be able to get back on track pretty quickly.
Anyway, hope this better explains things. Sure helped us! :)
Vista introduced an interface: IFileDialog::SetFilter, which allows me to setup a filter that will be called for every potential filename to see if it should be shown to the user.
Microsoft removed that in Windows 7, and didn't support it in XP.
I am trying to customize the our Open file dialog so that I can control which files are displayed to the end user. These files are marked internally with a product-code - there isn't anything in the filename itself to filter on (hence file extension filters are not useful here -= I need to actually interrogate each one to see if it is within the extra filter parameters that our users specified).
I would guess that Microsoft removed the SetFilter interface because too often it was too slow. I can imagine all sorts of similar ideas to this one which don't scale well for networks and cloud storage and what have you.
However, I need to know if there is an alternative interface that accomplishes the same goal, or if I really am restricted to only looking at the file extension for filtering purposes in my File dialogs?
Follow-up:
After looking further into CDN_INCLUDEITEM, which requires the pre-vista version of OPENFILENAME, I have found that this is the most useless API imaginable. It only filters NON-filesystem objects. In other words, you can't use it to filter files. Or folders. The very things one would filter 99.99% of the time for a file open or save dialog. Unbelievable!
There is a very old article by Paul DiLascia which offers the technique of removing each offending filename from the list view control each time the list view is updated.
However, I know from bitter experience that the list view can update over time. If you're looking at a large folder (many items) or the connection is a bit slow (heavily loaded server and/or large number of files), then the files are added to the dialog piecemeal. So one would have to filter out offending filenames repeatedly.
In fact, our current customized file open dialog uses a timer to look at the view's list of filenames periodically to see if any files of a given pattern exist, in order to enable another control. Otherwise it's possible to check for the existence of these files, find none, but a moment later the view updates to have more filenames, and no events are sent to your dialog to indicate that the view has been changed. In fact, my experience with having to write and maintain code for the common controls file dialogs over the years has been that Microsoft is not very cluefull when it comes to how to write such a thing. Events are incomplete, sent at not-useful times, repeated when not necessary, and whole classes of useful notifications don't exist.
Sadly, I think I might have to give up oh this idea. Unless someone has a thought as to how I might be able to keep up with the view spontaneously changing while the user is trying to interact with it (i.e. it would be awkward to go deleting out entries from the list view and changing the user's visual position, or highlighted files, or scroll position, etc.)
You need to initialise the callbacks for your CFileDialog. Then you need to process CDN_INCLUDEITEM notification code to include or exclude items.
You can also check this great article. The author uses some other approaches in addition to callbacks
As you have already discovered, starting in Windows 7 it is no longer possible to filter out files from being displayed based on content, only file extension. You can, however, validate that the user's selected file(s) are acceptable to you before allowing the dialog to close, and if they are not then display a message box to the user and keep the dialog open. That is the best you will be able to do unless you create your own custom dialog.
It seems, the way "list" processor works, we can't put them in middle of a flow. Then how to set attributes to ListHDFS? e.g. if I want to parameterize "directory", and pass it at runtime.
You can use expression language in the Directory property, but only to reference variables, system properties, or dynamic EL expressions, but not flow file attributes.
ListHDFS (and the other List processors) are made to track state and determine which files are new from the previous listing, so if you were allowed to specify the directory from an incoming flow file this would mean that the directory could change at any moment which then makes the previous state no longer meaningful, or would mean that it would need to track state for N number of directories which could grow large and would be unclear when a directory was no longer being listed.
It may be helpful to implement another processor that allows dynamic listings, but does not store state,
In case, someone runs into this question, GetHDFSFileInfo would be what you are looking for.
I have a MacOS app that creates many NSViews of differing types, some of which contain WKWebViews. The Number of WKWebViews can become fairly large (dozens or more).
The problem is that each of these WKWebViews creates several processes, as can be easily seen in Activity Monitor. When the number of processes becomes too large, the entire system essentially grinds to a halt: running apps still function slowly, but new apps can't be launched, the Finder stops working, and the system must be rebooted.
So I am looking for a way to control the number of processes started by WKWebViews.
According to Apple docs, this is managed by the processPool property of WKWebView, as they state: "The process pool associated with a web view is specified by its web view configuration. Each web view is given its own Web Content process until an implementation-defined process limit is reached; after that, web views with the same process pool end up sharing Web Content processes." (from the page at: https://developer.apple.com/documentation/webkit/wkprocesspool?language=objc).
I cannot figure out how to define that "implementation-defined process limit". When I NSLog the description of the WKWebView's configuration, I get this:
WKWebView configuration description:
>; preferences = >
I can see there's a processPool and a configuration for it (called _WKProcessPoolConfiguration), and a value called maximumProcessCount, which is set to 0. I am assuming that 0 means that the process count is unlimited, and I would like to set it to a reasonable number. But I cannot figure out how to set this value! The processPool itself has no properties, so I have no idea how to access this maximumProcessCount value.
Any help is greatly appreciated.
you can use singleton WKProcessPool and all wkwebview.configuration.processpool use that WKProcessPool singletonï¼›
it will resolve cpu too high.
The documentation for NSDocument states:
Subclasses can override this method and use it to restore any
information that would be needed to restore the document’s window to
its current state. For example, you could use this method to record
references to the data currently managed by the document and displayed
by the window. (Do not store the actual data itself. Store only
references to the data so that you can load it later from disk.) You
must store enough data to reconfigure the document and its window to
their current state during a subsequent launch of the app.
What does "Do not store the actual data itself." actually mean? Is this a hard and fast rule? Or is it more of a guideline?
In particular, I'm wondering about the case of documents with unsaved changes in them. Is it "permissible" to store the unsaved changes (which may be everything if this is a new document)? Or, do I need to save the data off in a file somewhere... and if so, where is the preferred location?
I don't want to restore a bunch of identical (blank) documents if I had multiple unsaved new documents when the application was shut down.
Thanks for any hints on the proper way to handle this.
Never mind. It hit me in the shower this morning (where I make most of my tech breakthroughs).
I am pretty sure now that the key is to get autosaving working with my application.