I have a question that I can't really answer, so I wonder if someone may shed some light here.
Basically I am interested in knowing what is going on in iOS before and while I run an app...but from the OS perspective.
I've seen a lot of posts regarding what happens when the user tap on an app in the main screen, but I am interested in knowing basically what happens behind the scenes, before that the app takes control and main runs the singleton for UIApplication. And also once that the app is running, is the whole OS blocked in the main run loop of the app or something else is going on?
In particular, I would like to understand who creates the process where UIApplication will run (so the whole app will run inside that process, I assume).
Also would like to know what is the OS doing when for example, I open a connection in an app...since I see that a new thread is created (looking at a crash report I see a bunch of threads running, not just the main one), but I don't get where and who creates them (UIApplication itself?, where they running already before launching the app?).
Hope that the question is clear; I've search all over to find info but all that I get is that when you tap an app, main() runs and calls UIApplication,which takes control, deal with the delegate and views and so on...but what is going in the OS is a mystery.
Is there any resource related to the iOS part? Thanks!
The operating system of the iPhone works really similar to any other modern operating system. There is a kernel which provides low level functions, an API that provides high level functions (either to applications either to the OS itself) and so on.
There are a lot of processes always alive in the OS itself, just think about the fact that the device is able to receive notifications, receive calls, manage connections and whatever it needs to run.
When you launch an application the only thing that changes is that a process is launched and the control of it is given to the application.
And also once that the app is running, is the whole OS blocked in the main run loop of the app or something else is going on?
The whole OS is not blocked, the process launched is just scheduled together with many other processes that constantly run. This is achieved by multi-tasking.
In particular, I would like to understand who creates the process where UIApplication will run (so the whole app will run inside that process, I assume).
The process is created by the OS itself, which istantiates a new process structure to manage the just launched application and schedule it (with a high priority since it will run in foreground).
(UIApplication itself?, where they running already before launching the app?).
Threads are similar to processes in the sense that they have their code and they actually do something but a thread is lightweight because many thread can be managed by just one process. This mean that your application (or an API call) can create a thread which will run together with the main thread of your application and manage their operations but all these thread will share the same CPU allocation time and the same memory space and whatever. Actually Cocoa hides many of the details from a developer point of view, so that you don't care exactly about which threads are automatically started by the application because you don't need to: they are used to dispatch messages between objects, to manage asyncronous events and whatever.
But this is just the tip of the iceberg, before understanding how iOS works you should learn how a lower level infrastructure works, eg BSD Unix which is actually one of the ancestors of Darwin, which is the kernel on which iOS is operating. After understanding how it works you will undersand also how the infrastructure over it works (which is iOS + its API).
Related
I am working with SceneKit in an iMessage extension and have run into a peculiar little beast of an issue. I am trying to render a custom scn model and rig nodes to a users facial expression using blend shape anchors. I am able to do this succesfully in the iOS app that this iMessage extension is born from without an issue. However, once placed into a MessageViewController the program exits with code 0 every time I try to run it.
I did a bit of digging and it seems "exited with code 0" is indicative of memory overload so I started playing around with my models nodes. I discovered that if I delete all nodes but one, I am able to animate that node with its corresponding blend shape. Any more than one node and it crashes.
Does anyone have any ideas as to why this is happening? Or any proof that iMessage extensions are only granted a certain amount of processing power before they are killed off (another theory of mine)?
Appreciate any help!
from the App Extension Programming Guide we learn that
Memory limits for running app extensions are significantly lower than the memory limits imposed on a foreground app. On both platforms, the system may aggressively terminate extensions because users want to return to their main goal in the host app. Some extensions may have lower memory limits than others: For example, widgets must be especially efficient because users are likely to have several widgets open at the same time.
Your app extension doesn’t own the main run loop, so it’s crucial that you follow the established rules for good behavior in main run loops. For example, if your extension blocks the main run loop, it can create a bad user experience in another extension or app.
Keep in mind that the GPU is a shared resource in the system. App extensions do not get top priority for shared resources; for example, a Today widget that runs a graphics-intensive game might give users a bad experience. The system is likely to terminate such an extension because of memory pressure. Functionality that makes heavy use of system resources is appropriate for an app, not an app extension.
One option may be to try to optimize your geometry in your DCC so you don't run into system resource constraints.
I have an app on the app store that uses AFNetworking 2.x to download large files in the background with NSURLSession-based downloads, because the user will often put the app in the background (it gets terminated after a while of course, but the downloads finish all the same. Wonderful). This app is working well. Usually users are only downloading a few files at a time.
Now I need to make another similar app, but this time instead of a few large files, it is very likely that the user will want to download a large number of smallish files: for example, 500 files that are 1-5mb each. Again, the app will often be put in the background, so I want to stay with NSURLSessionDownloadTask unless there's a really good reason not to.
My question is, can I simply create 500 NSURLSessionDownloadTasks all at once? Does AFNetworking do some clever throttling so as not to overload the system? Or does iOS do it? Or does nothing do it, and I have to painfully track & organize the state of transfers across restarts of my app (ie. because it gets put in the background eventually terminated) ?
If anyone knows the limits of how many NSURLSessionDownloadTasks you can create reliably simultaneously, that would be awesome...
thanks!
p.s. I greatly prefer obj-c to swift, thx :)
Last I checked (haven't looked at the iOS 9 betas), task creation was unexpectedly expensive and also superlinear. On my test runs:
50 tasks -> ~1.5s
200 tasks -> ~11.5s
500 tasks -> ~55s
Since my file count was often a 5-digit number, scheduling everything at once wasn't a solution for me. My approach (which isn't in production yet, I stopped working on the feature in favour of other things), combines persistence with NSURLSessionDownloadTask and uses the session identifiers to sort out which logical download a particular file belongs to. Further downloads are scheduled from one of the delegates depending on whether I'm on the normal lifecycle or coming from -application:handleEventsForBackgroundURLSession:completionHandler: (debugging this situation can get painful; NSUserDefaults is your friend). The theory seems sound, I can see that tasks do get scheduled, but I'm currently stuck getting the iOS downloader daemon to conform to my will.
If the server-side zip as suggested by Benjamin Jimenez is an option for you, do yourself a favour and use that instead.
The Apple staff member "eskimo" on apple developer forums helped me find the answer, which you can see in this forum post:
https://forums.developer.apple.com/thread/11621
Pasting here the relevant parts:
(me) I've read through this thread and the one you linked to here
(https://devforums.apple.com/message/938057#938057) and I have a
question about best practices to download 10,000-20,000 files via
NSURLSessionDownloadTasks. (Disclaimer, i'm using AFNetworking 2.x).
I'm targeting iOS 8 and newer, so answers do not have to work on iOS
7. How can we compute a reasonable batch (group) size ? I understand the resume-rate limiter means one wants the batch size to be higher,
but there's an unknown max limit of simultaneous task requests that
will crash the daemon.
(me) My assumption here is that when the user opens my app and it runs
for some time in the foreground, then the rate limiter is "reset" or
similar -- so now things will flow nicely again. Is this assumption
correct?
(eskimo) Yes. Also, starting with iOS 8, if the user brings your app
to the front then iOS will automatically give tasks a 'kick'. I've
forgotten the exact mechanics of this but I'm pretty sure it's covered
in WWDC 2014 Session 707 What's New in Foundation Networking.
I have a game that I'm getting ready to submit. I've tested it a lot and it seems to be solid -- no crashes and no unexpected behavior. I am not forcing anything to run on the main thread (except for one place where I followed a sample in a book) and now I'm concerned that under some circumstance, on somebody else's device, the game will not work right or crash because I'm not doing something on the main thread that should be on the main thread. But I don't understand what needs to be run on the main thread. I googled for a checklist or summary of what methods need run on the main thread and didn't find anything useful. Is this something I need to worry about? The app is for iOS 5.1 and up and it uses in-app purchases and Game Center. I use the cocos2d framework and also a lot of UIKit stuff.
most methods running on the main thread are fine,
especially the UI,
you want to use the back thread for processes that can take long, like http requests, database or data sorting, or any other process that can pause the user experience while is processing.
if you load lots of objects you can produce a memory warning that can result in a crash,
so you can release non needed objects when you get a memory release.
good luck
I have an application which needs to run several other applications in chain. I am running them via ShellExecuteEx. The order of running each of the apps is very important cause they are dependant on each other. For example:
Start(App1);
If App1.IsRunning then
Start(App2);
If App2.IsRunning then
Start(App3);
.........................
If App(N-1).IsRunning then
Start(App(N));
Everything works fine but there is a one possible problem:
ShellExecuteEx starts the application, and return almost immediately. The problem might arise when for example App1 has started properly but has not finished some internal tasks, it is not yet ready to use. But ShellExecuteEx is already starting App2 which depends on the App1, and App2 won't start properly because it needs fully initialized App1.
Please note, that I don't want to wait for App(N-1) to finish and then start AppN.
I don't know if this is possible to solve with ShellExecuteEx, I've tried to use
SEInfo.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC;
but without any effect.
After starting the AppN application I have a handle to the process. If I assume that the application is initialized after its main window is created (all of Apps have a window), can I somehow put a hook on its message queue and wait until WM_CREATE appears or maybe WM_ACTIVATE? In pressence of such message my Application would know that it can move on.
It's just an idea. However, I don't know how to put such hook. So if you could help me in this or you have a better idea that would be great:)
Also, the solution must work on Windows XP and above.
Thanks for your time.
Edited
#Cosmic Prund: I don't understand why did you delete your answer? I might try your idea...
You can probably achieve what you need by calling WaitForInputIdle() on each process handle returned by ShellExecute().
Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.
If your application has some custom initialization logic that doesn't run in UI thread then WaitForInputIdle might not help. In that case you need a mechanism to signal the previous app that you're done initializing.
For signaling you can use named pipes, sockets, some RPC mechanism or a simple file based lock.
You can always use IPC and Interpocess Synchronization to make your application communicate with (and wait for, if needed) each other, as long as you code both applications.
What's the best way to terminate a program and then run additional code from the program that's being terminated? For example, what would be the best way for a program to self update itself?
You have a couple options:
You could use another application .exe to do the auto update. This is probably the best method.
You can also rename a program's exe while it is running. Hence allowing you to get the file from some update server and replace it. On the program's next startup it will be using the new .exe. You can then delete the renamed file on startup.
It'd be really helpful to know what language we're talking about here. I'm sure I could give you some really great tips for doing this in PowerBuilder or Cobol, but that might not really be what you're after! If you're talking Java however, then you could use a shut down hook - works great for me.
Another thing to consider is that most of the "major" apps I've been using (FileZilla, Paint.NET, etc.), are having the updaters uninstall the previous version of the app and then doing a fresh install of the new version of the application.
I understand this won't work for really large applications, but this does seem to be a "preferred" process for the small to medium size applications.
I don't know of a way to do it without a second program that the primary program launches prior to shutting down. Program 2 downloads and installs the changes and then relaunches the primary program.
We did something like this in our previous app. We captured the termination of the program (in .NET 2.0) from either the X or the close button, and then kicked off a background update process that the user didn't see. It would check the server (client-server app) for an update, and if there was one available, it would download in the background using BITS. Then the next time the application opened, it would realize that there was a new version (we set a flag) and popped up a message alerting the user to the new version, and a button to click if they wanted to view the new features added to this version.
It makes it easier if you have a secondary app that runs to do the updates. You would execute the "updater" app, and then inside of it wait for the other process to exit. If you need access to the regular apps DLLs and such but they also need updating, you can run the updater from a secondary location with already updated DLLs so that they are not in use in the original location.
If you're using writing a .NET application, you might consider using ClickOnce. If you need quite a bit of customization, you might look elsewhere.
We have an external process that performs updating for us. When it finds an update, it downloads it to a secondary folder and then waits for the main application to exit. On exit, it replaces all of the current files. The primary process just kicks the update process off every 4 hours. Because the update process will wait for the exit of the primary app, the primary app doesn't have to do any special processing other than start the update application.
This is a side issue, but if you're considering writing your own update process, I would encourage you to look into using compression of some sort to (1) save on download and (2) provide one file to pull from an update server.
Hope that makes sense!