Obj-C, how can I log to a file how long a method took in seconds? - objective-c

I envisage I'll run into problems as i haven't done this before.
I'm thinking that I can either define a date at the start of the method or initialise a class.
Then at the end of the method, call the commit method, which will write the time taken about with some sort of code to determine where the measurement was made.

Since you're crashing before the app finishes launching, so no code is going to fix this. If TestFlightApp isn't working, any other code-based solutions are likely to have the same problem.
As #dasblinkenlight noted, NSLog timestamps, so that's a really easy first step. Then you need to get the logs.
If possible, have your user install and run the iPhone Configuration Utility. Have her connect her device and select it from the Devices list. Then select Console and "Save Console As..." She can then mail it to you.

Related

What exactly should I pass to -[NSApp activateIgnoringOtherApps:] to get my application to start "naturally" in comparison to most other OS X apps?

When I learned how to start NSApplications on my own, the code I used (based on here and here) did
[NSApp activateIgnoringOtherApps:YES];
which forces the app to the front at startup.
I'd like to know what most other apps do. I want to be able to run programs both directly from the binary and from an app bundle, and I'm not using Xcode to build this (raw building). So I'd rather this act naturally, so to speak.
The docs do say Finder issues NO, but... why Finder? Isn't this a method that's run from within the process, not outside? (I'm not in control of the choice.) And what about the Dock and other possible entry points?
I even went so far as to disassemble 10.8's NSApplicationMain() to see what it did, but as far as I can tell from the 32-bit version, unless this "light launch" thing issues this selector, this selector is never called.
Is there an answer to this question? Thanks... and sorry if this is confusing; I tried to word it as clearly as possible.
Apps normally do not call -activateIgnoringOtherApps: at all. And, generally speaking, shouldn't. Certainly, it wouldn't be in NSApplicationMain(), which is too early and fairly distantly related to actual app start-up.
Apps are normally launched by Launch Services (which is what is used by the Finder, the Dock, and /usr/bin/open, as well as any other app that might open yours or a document which yours handles). Roughly what happens is that Launch Services deactivates the app which called it to open something else and then, in the launched app, Cocoa's internals do something like (but not necessarily identical to) [NSApp activateIgnoringOtherApps:NO]. In this way, the launched app only activates if nothing else was activated in the interval between those two events. If that interval is long (because something was slow) and the user switched to something else in the meantime, you don't want to steal focus from whatever they switched to.
You should only call [NSApp activateIgnoringOtherApps:YES] in response to a user request to activate your app in a context which won't include the automatic deactivation of the current app by Launch Services. For example, if you have a command-line program which transforms itself into a GUI app (using -[NSApplication setActivationPolicy:] or the deprecated TransformProcessType()), then the user running that tool means they want it active. But Terminal is active and won't be deactivated spontaneously just by virtue of having run your program. So, the program has to steal focus.
If your program is a bundled app, then running it from the command line should be done with /usr/bin/open rather than directly executing the executable inside the bundle. Then, you don't need to call -activateIgnoringOtherApps: at all and the question of what value to pass is moot.

NSTask subprocess stuck in _dyld_start

I use NSTask to run my helper application. On 99% one my customer systems this works fine, but two got back to me letting me know it doesn't. One of them was nice enough to let me look into the issue per remote desktop.
I tried a lot of different NSPipe/NSFileHandle combination for StandardOutput/StandardError to make sure the problem is not related filling up these buffers. Example 1 and 2. My guess is that it is not related because it works fine on so many systems and _dyld_start is too early on in the application lifecycle to fill up StandardOutput/StandardError.
Other notes about the problem:
Launching the helper app from the terminal works fine.
Attaching and detaching the gdb on the stuck process and after-worth it works fine and when it finished NSTask picks up work after -waitUntilExit.
Using fork(2) and execv(3) instead of NSTask is able to launch and run the helper fine.
The parent process is sandboxed but I think previous reports where non-sandboxed on Mac OS X 10.6/10.7.
Screenshot of the process Sample from Activity Monitor:
Any clues or debugging tips to figure out why the helper is stuck in _dyld_start are welcome!
Since nobody answered, I am throwing a few ideas. Maybe one of them is the answer – only guessing – but since clues and tips are welcome, you could take a look at:
the list of the loaded libraries in the crash dump (there may be a clue there)
any error that would happen in the child process (after the fork). However, I see why it could be difficult to get back any post-fork error.
If I recall correctly, NSTask calls posix_spawn(2). This may be a clue, since using fork(2) and execv(3) seems working, you could focus on the differences between NSTask and the non-blocking alternative. Clearly, something is happening at the very beginning that prevents the child from executing properly.
Are you sure it is stuck and not crashed? As far as the user could tell, your app your app wouldn't look like it crashed. Only the child process would crash.
As a last resort, you could try to look for any Mach exception occuring (if
any, that would mean an error, which you wouldn't be able to
recover anyway. But it would provide valuable clues nonetheless).
You can tell willing custommers to send you their sysdiagnose. To this goal, ask them to hit Command + Option + Control + . + Shift to wait a few minutes. Soon after, their finder should pop a window to reveal a file named: sysdiagnose_timestamp_.tar.gz. Kindly ask them to mail it to you. Mine is around 5 MB. More details on the sysdiagnose man page.

iOS - wait till a process ends

This is an IOS6 question.
I have an app that is calling a class (A) to check something. Then I want to call a class (B) to do something else
Is it possible to make sure process B doesn't start before process A finishes?
At the moment, I just call one after the other in the RootVC.
Each is showing a modal view, and I only get to see B ..
[self performA];
[self performB];
Thanks
There are several tools for managing the order of execution of parts of your application available to you. However since you are presenting view controllers you have a couple of constraints; you don't want to block the main thread (or else the app will become unresponsive) and you must perform UI actions on the main thread.
In this case the most common, and probably most appropriate, solution is to setup a callback to trigger action B when action A finishes.
The modal view controller presented as part of A might call a delegate when it has finished its task successfully. That delegate can then begin task B.
Alternately you might pass a block to A which A will execute when it finishes. That block can then perform task B.
I took the dare and failed.
The story: My app has been giving me hell updating from an iOS4 target to iOS6 (with a contingent sub of code for iOS5/3GS). It crashes unless i use #try etc... with a built in delay interval on the reattempt (which is stupid, 'cause I don't know how large a database the users have, nor how long it will take to load them). It's a painful way to get around my real problem: the view loads before the CoreData stack (logs) can be loaded completely and I don't see a way to make the initial view wait until its NSMutableArray (based on the CoreData database of my object) loads. Basically, I keep getting a false error about addObjectsSortedBy: the foremost attribute of my entity.
Threading does seem to be the answer, but I need to load an NSMutableArray and feed it into my initialViewController, which will be visible on every launch (excluding FirstTime initial), but my attempt (okay, 12 attempts) to use threading just made the crash occur earlier in the app launch.
The result: I bow down to those who have wrangled that bull of threads.
My solution has been to build in a notification in the AppDelegate.m, my initialViewController viewDidLoad is told to listen for it before anything else. If it gets the notification it skips ahead and completes the normal process unto [super viewDidLoad]; if not, it executes #try, #catch, #finally. In the #try I attempt to proceed as though the notification arrived (like it was a little late), then I handle (#catch) the error by displaying a "Please Wait" label to the user, then I tell the app to wait .xx and repeat the original addObjectsSortedBy: command as though everything were kösher to begin with.The sweet-spot for my app, with images and data in the logs appears to be .15 for the wait interval #50 test entries, with time to spare and no obvious lag on load. I could probably go down to .10 #50 entries.
BUT: I don't know how to scale this, without having the logs loaded enough to get an object.count! Without that, there is no way to scale my delay, which means it may (read:will) not work for large logs with many entries (200+)!
I have a work-around, but I'm going to keep trying to get a grip on threading, in order to have a solution. And to be honest, once I hit 20 entries, the notification never hits in time for the #try to occur.
If you can, use threads. I painted myself into a corner by failing to do so early on and am paying for it: my app has been in need of an overhaul, but I need this notch in my belt before it will be worthwhile. The earlier you can implement threaded loading the better for your long-term development. In the meantime, you may be able to use my work-around to continue testing other parts of your app.

Is a file available to be opened?

Short version: I think I'm asking for a file too soon, but it's pretending like it's ready. Am I missing something?
Slightly longer version: I am writing files to disk. Before I do so, I have the user add some meta data, including the new file name. Once the user is done, the screen goes away and the program writes the file to disk. The user can then look at a list of files. That list is generated by reading the contents of a folder. The new file is in the list of files, but when I try to extract info from the file to display (e.g. file size) the program crashes. As best as I can tell, the crash occurs because, while the file is there in name, it's not available to be read. (By the way, these are small files - a few hundred k.)
First, is it possible that a file shows up in the directory but isn't all there yet?
a
And second, if so, how do I check to see if the file is ready to be read?
Thanks much.
UPDATE:
Thanks. I'll try to add more info. I'm recording an audio file with AVAudioRecorder. The init line is:
soundrecording = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error];
The program goes through it's UI updates and metering and all that. When the audio is stopped, I call:
[soundrecording stop];
and when everything else is updated and ready to move on, I call:
[soundrecording release];
soundrecording=NULL;
As far as I understand, this should take care of releasing the file, yes?
Thanks again.
The first thing I would do is confirm that you're right about the file not being ready yet. To do that, sleep your program for a second or two after writing and before reading. A few hundred KB should not take longer than that to be ready.
If it still fails, my guess is that you haven't closed the file handle that you used to write it. It may be unready for reading because the file system thinks you might keep writing.
Usually, the way to check to see if a file is ready is to attempt to open it. If that succeeds, you can read it. Or if it fails with an error, you can handle the error gracefully:
In a command-line utility, you might print the error and quit, and the user could try again.
If it's a background program that should not quit, like a server, you could log the error. You might also try again automatically after a delay. If it's a big deal kind of error, you might want to have the program email you about it.
In an GUI window app, you probably want to show an error dialog or panel, and then give the user an opportunity to retry.
Now that you have added sample code, I can say some more.
First, the class reference seems to say that the stop method will close the file. However it also seems to suggest that there is an underlying audio session going on, and possibly some conversion. I think I recall that the iPhone's Voice Notes app, which probably uses this API, has to do some work to compress a long recording after it's completed.
So I support your hunch. I think that your file may not be closed yet, but on another thread that is processing the recorded data into a proper format to save.
You probably want to set a NSTimer to attempt to open the file every second or so, so that your user interface can perk up when it's done. You probably want to show a "Please wait" sort of message in the meantime, or otherwise let the user know it's working.

Unattended application best practice question

We have an unattended app w/o a user interface that is is periodically run.
It is a VB.NET app. Instead of it being developed as a service, or a formless Windows application, it was developed with a form and all the code was placed in the form_load logic, with an "END" statement as the last line of code to terminate the program.
Other than producing a program that uses unneeded Windows form resources, is there a compelling reason to send this code back for rework to be changed to put the start up logic in a MAIN sub of a BAS file?
If the program is to enter and exit the mix (as opposed to running continuously) is there any point in making it a service?
If the app is developed with a Form do I have to worry about a dialog box being presented that no one will respond to even if there are no MessageBox commands in the app?
I recall there used to be something in VB6 where you could check an app as running unattended, presumably to avoid dialogs.
I don't know whether there are conditions where this will not run.
However, if the code was delivered by someone you will work with going forward, I would look at this as an opportunity to help them understand best practices (which this is not), and to help them understand that you expect best-practice code to be delivered.
First of all, you don't need it to be run in a Form.
Forms are there for Presentation, so it should not be done there.
If you don't want to mess with converting the application a Service (not difficult, but not very easy neither), you shoud create a Console Application, and then, schedule it with Windows Task Scheduler.
This way, you create a Console Application, with a Main function, that does exactly what you need.
Anyway, the programmer could show windows, so there should not be any messagebox. Any communication should be done via Logging to: local files, windows events, database.
If you want more information on any of them, ask me.
If you don't want it to be a service, nothing says that it has to be a windows service. Scheduling it to run via the Task Scheduler or something similar is a valid option.
However, it does sound like the developer should have choose a "Console App" project, instead of a "Windows Forms" project to create this app.
Send it back. The application is bulkier and slower than it needs to be, although that won't be much of an issue. It is somewhat more likely to run out of resources. But the main reason: converting it to a console app is very easy.
If you don't prefer for the Console window to popup, simply do the following.
Create a new class "Program.vb", add a public shared Main() method, and move the "OnLoad" logic from the form to this method.
Next delete the form, and change the project start up object (Available in the project properties window) to use the Program.Main instead of the Form.
This will have the same effect, without the windows forms resources being used. You can then remove the references to System.Windows.Form and System.Drawing.