Monitoring a folder in sandboxed application - objective-c

How would I monitor the users Trash so that when a file is added I can send an action.
Thanks in advance!

A sandboxed application cannot access the Trash. Sandboxed applications are sandboxed for security reasons and in the Trash may be all kind of documents a user has deleted and that a sandboxed application would have never had access to in their former destination. Of course a user expects that those files are still save once they are put into the Trash.
If it really makes sense for your app to access the Trash, e.g. because it is a Trash Management app (stupid example, I know), Apple will still grant your application access to the Trash, if you only ask for it. Therefor you need to specify a Temporary Exception Entitlement, either of the type
com.apple.security.temporary-exception.files.home-relative-path.read-only
if read-only access is enough for you or
com.apple.security.temporary-exception.files.home-relative-path.read-write
if you also need write access. Those are the keys in the entitlement dictionary and the value is an array of strings, each string specifies a directory. In your case they array would contain /.Trash, which translates to /Users/<username>/.Trash for the current user. E.g.:
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array>
<string>/.Trash</string>
</array>
This will allow your app to be partially freed from its sandbox, as long as it only accesses this directory (or its sub-directories).
Note that Apple will only approve an app that uses one of the Temporary Exception Entitlements under certain conditions which are listed on the App Store Connect webside (you must login to see that side and you need an Apple ID with permission to use App Store Connect).
AFAIK those conditions include that you must file a bug report with Apple's Feedback Assistant (again, you must log in to the webside, but this time every Apple ID is allowed to log in) and you must explain Apple why you need this exception as otherwise your app cannot do whatever it is supposed to do. You better be good at explaining that! If Apple doesn't consider your use case legitimate, they will close this bug as invalid and then your app submission will be rejected. If the bug is considered valid, you must tell Apple that your app uses a temporarily entitlement when you submit the App and you must point Apple to the bug report you have created. They will read it again and if the store team agrees with the development team that this is a valid reason, they will allow your submission to pass through.
Once your app has the appropriate entitlement, you should be able to monitor Trash the same way as a not sandboxed app can do so. E.g. using the FSEvent API. With the function FSEventStreamCreate() you can create a FSEventStreamRef that monitors a certain path (in your case the Trash), calls a user defined callback function whenever the contents at this path changes and can be scheduled on a RunLoop. Once scheduled, whenever the content of the directory changes, the callback function is called. In the callback function you may do whatever you want to do, e.g. to get a higher level event (since the callback function is only plain C, so you may want to post a NSNotification that you can handle in your Obj-C code, e.g. in your UI code) or maybe directly call an Obj-C method of some object (stored in the callback context, a global variable or which is accessible as a singleton, etc.)

Related

iphone Addressbook caller blocking

Since iOS7 it's possible to block a caller when she/he calls your phone...
Is it possible to change this setting from within an app?
The idea is having an app that lets the user block people temporarily from calling them. Another option would be to send them directly to voicemail or send them a (predefined) text-message if they're calling.
I don't need code, just a hint whether this would be possible and which settings I'd have to change.
No, it's not possible from within app. Apple hasn't provided any such API. Check here

iOS SDK: Working with NSUserDefaults

With the NSUserDefaults class, you can save settings and properties related to application or user data.
now i have tow question :
( settings and properties ) Where are stored ?
if =>The objects will be saved in what is known as the iOS “defaults system"
then : What is iOS “defaults system"
How long will remain stored ?
Where? It depends on what kind of app you're developing. For AppStore applications, in the sandbox folder of your installed app folder, more precisely in the Library/Preferences folder. The actual file that contains the settings is a PLIST (property list) file whose name matches the bundle identifier of your app.
All in all:
(/var/mobile/Applications/XXXX-XXXX-XXXXXX-XXXXXXXX/MyApp.app/Library/Preferences/com.mycompany.bundleid.plist
(where XXXX etc. is an UUID).
If you're making an app for jailbroken devices (i. e. a Cydia app), it will be a plist file again, whose name matches the bundle ID, but it will be installed in
/var/mobile/Library/Preferences/com.mycompany.bundleid.plist
The iOS defaults system is the part of the Foundation framework, iOS itself and the files and directories altogether which manage, store and modify your preferences/settings/defaults.
How long? Again, it depends on what kind of app you are writing. For a normal AppStore app, the defaults are persited to the file - but only as long as the user doesn't delete your app. When your app is deleted, the whole sandbox, app bundle and od course the user defaults will also be gone. Forever, irreversibly.
If you develop a jailbroken application which resides in the system apps' directory (/Applications), then the user defaults file will be available in /var/mobile/Library/Preferences even if the user deletes your package/application, as APT (the backing package manager of Cydia) only makes note of the files your package originally contained, and that's not the case with the defaults property list file (which is only created when your app first accesses the NSUserDefaults class.) If the user manually deletes the file or restores to a stock firmware, it'll be gone.
Answers:
In the application's sandbox. Where exactly is unimportant as you aren't going to be accessing the defaults directly anyway.
As long as your app is on the device. If you delete the app, the sandbox is deleted as well, so that's when they get deleted. If you update your app, the same sandbox is used, so they don't get deleted.
As for what it is, I'm just going to quote you a bit of the documentation:
The NSUserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an application to customize its behavior to match a user’s preferences. For example, you can allow users to determine what units of measurement your application displays or how often documents are automatically saved. Applications record such preferences by assigning values to a set of parameters in a user’s defaults database. The parameters are referred to as defaults since they’re commonly used to determine an application’s default state at startup or the way it acts by default.
At runtime, you use an NSUserDefaults object to read the defaults that your application uses from a user’s defaults database. NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. The synchronize method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.

Mac App: Storing Information w/ Document-based Applications

I'm in the process of planning out the infrastructure for a Mac App, and we have a startup screen with many user files listed. We want the App to be iCloud-compatible (thus the need for Document-based (key-value won't cut it since they aren't nested - correct me if I'm wrong here)). Essentially, we don't want to have the user keep track of each individual file themselves as that would be irritating, but rather store it in the App's folder until the user needs it (i.e. Email, Export, etc). It would eliminate a lot of the friction in the app, we think. I guess my question is:
Is it possible to store files automatically in the App's installation folder (or somewhere locally?) without bothering the user - in a Document-based app - and still be App Store compatible? Seems like the ideal solution - user opens app, App knows it's save location and automatically saves documents there when a user creates one, and pulls them to share if needed. Any help?
Yes, it's possible. You won't want to store document's in the application's installation folder. For one thing that'll violate the App Store rules, but it's bad behavior anyway, since Applications are normally installed in /Applications, which shouldn't be cluttered up with other files. So storing things in ~/Library/Application Support/YourAppName is the way to go.
To actually implement this, take a look at NSDocumentController and NSDocument itself. You'll basically want to override/modify any UI that allows users to choose a location to save/open documents. Instead, just let them name the documents, and then automatically save them with the given name in the app support folder. Then create a UI that allows them to browse and open those files within the app.

What is the standard method for writing a continuously running app that is allowed on the Mac App Store

I'm brand new to OS X and mac programming. I'm looking to write an app that runs continuously or is woken up every 30 seconds to do some minor task. It would do something like check the weather via a web service and shoot off an email if the temperature drops below freezing. In Windows I would just use a service or put a repeating task in the task scheduler. Is there a standard way to accomplish this in OS X which the mac app store allows? I would like to write something that I can put in the store but Apple seems to have vague restrictions against running background processes.
I've learned a little about launchd but I can't tell if I am allowed to use it. Ideally the process would get run even when no one is logged in, but it probably won't need root access. If someone does happen to be logged in, it would trigger some popup if it sent an email temperature alert out. I would also have some GUI which the user would be able to modify the configuration files that determine the behavior of the background process. I don't anticipate any app store restriction for that piece of the project though.
I'm pretty sure an app that runs invisibly like that would not be allowed into the App Store. What you're going to want is to create a menubar-only application, which can be enabled by setting a key in your app's info, namely LSUIElement. Although it won't be able to be run unless a user is signed in, it's your only way to get it into the store successfully.
The MAS guidelines have several prohibitions that would impact you. Go to the guidelines and read section 2. In particularly consider 2.15, 2.23, and 2.27. I don't know any way to get your application running prior to login without at some point requesting admin privileges (even if you don't use the privilege when you run).
I would probably make it a Login Item (System Preferences>Users>Login Items), probably as an LSUIElement app as sudo rm -rf suggests. Definitely if it's your first app, I wouldn't go diving into launchd in any case. It is one of the most infuriating system processes I've ever dealt with.

Changing provided services based on user preferences in OSX?

I would like to be able to change the OSX services that my application provides based on the current user's preferences (like adding more, changing the name,...). This basically means modifying the Info.plist (NSService key), but I don't think it is a good practice when an application modifies its own Info.plist while running, right? (At least based on few searches here). Is there any other option how to get this functionality?
I guess it should always be an external entity who does modify the Info.plist? So far I can only think about providing a system preference bundle which will do the modification in the actual app? Do you have any ideas?
Thank you
One way would be to install a service in ~/Library/Services that provides the services, and edit that application's Info.plist from your main application.
Of course, that should be an explicit action, so the user (hopefully) knows to delete the service if they delete your application. And you should document that procedure on your product's support web page, just in case they don't.
Here's a small twist to the previous recommendations, create a separate app that handles the service and bundle it within your Resources. When you want to enable the service, instead of copying the file over to ~/Library/Services, create a symbolic link within the ~/Library/Services folder that points to the app you bundled in your Resources.
This way if the user deletes your application, all that will be left behind is a symbolic link pointing to an invalid location. Does less arm than actually leaving the app behind and will have the added benefit that the service will no longer be available (since the info.plist will have been removed when the user deleted your app).