Best iphone questions in April 2011

Best process to show an OpenGL Animation in iPhone

9 votes

I'm having issues being able to import a bone and skeletal animation from Maya to Blender to iPhone. Here's what I've done:

  1. install the ColladaMaya plugin to export a DAE for Blender to export
  2. used Jeff LeMarche's script to be able to export a single keyframe of the model and import this .h file into the iPhone game
  3. Setup the GLView using more of Jeff LeMarche's steps and rendered into our Game, so this model display next to the actual game (not in 3D).
  4. Researched oolongngine, sio2 (applied but haven't yet gotten e-mail back from them), other SO q's for solutions, including mine from game dev
  5. Reviewed using FBX SDK content pipeline to dynamically generate class files for the animations.

I can import a model and display it. A lot of these processes respond to that issue and leaving the developer to manipulate the game object programmatically. My main issue is finding the best, defined process of importing an animation into iphone next to the existing game? I don't need a whole game, or a whole scene, just one animating model and some steps to follow.

This animation is meant to play in a loop. There are 3 more animations that will play on different game states (good move, bad move, etc.). So I'm concerned that LeMarche's keyframe solution (which basically means exporting EVERY keyframe as a .h file) will be incredibly time-intensive and memory-intensive. I'm definitely willing to do it, but after all the research I've done (additional links not included), I'm lost as to where to go next besides hand-exporting each keyframe and importing them.

EDIT:

I've added a bounty to this for anyone who can give me a clearly-defined process for importing an animation from a 3D application into iPhone. NOT the entire application itself (i.e. Unity, Sio2, etc.), but just showing a 3D overlay in an application (like an animating model next to a bejeweled-esqe game, not interacting with the world.)

People keep saying, "create your own model loader". Are there scripts, examples, tutorials, anything that walks through this "model loader" process from EXPORTING from the 3D application (preferably Maya or Blender) and IMPORTING this animation and rendering it in Objective-C?

I'm really not an expert about openGL but I know there's an ongoing initiative around Cocos3D (support of OpenGL integrated with Cocos2D framework) maybe you'll find some useful info here : http://brenwill.com/2011/cocos3d-importing-converting-collada-to-pod/

homepage: http://brenwill.com/cocos3d/

iOS 4 blocks and retain counts

8 votes

I'm just getting started with blocks and Grand Central Dispatch. I've been told (and read in the Apple Documentation) that any object referenced from within a block gets retained.

For instance:

^{  
    self.layer.transform = CATransform3DScale(CATransform3DMakeTranslation(0, 0, 0), 1, 1, 1);
    self.layer.opacity = 1;
}

"self" gets retained so it leaks. To avoid that, I need to assign self to:

__block Object *blockSelf = self;

and then use blockSelf instead of self inside my block.

My question is: what happens when your block has a lot more code and references several objects? Do I need to assign them all to __block objects? For instance:

^{  
    [self doSomething];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"prevName == %@", artistName];
    [request setEntity:entity];
    [request setPredicate:predicate];

    Object *newObject = [[Object alloc] init];
    [someArray addObject];
    [newObject release];
}

No. The problem occurs when your block retains an object which retains it. Your block will retain any object that it references, except for those annotated with __block. Hence:

// The following creates a retain cycle which will leak `self`:
self.block = ^{
  [self something];
};

self retains block, and block implicitly retains self. This will also happen if you reference instance variables of self.

// The following avoids this retain cycle:
__block typeof(self) bself = self;
self.block = ^{
  [bself something];
};

Variables annotated with __block are mutable (for pointers, that is, the address they point to can be changed); as a result, it makes no sense to retain that object, since you need to treat that object as a local variable (as in, it can be reassigned, affecting an object outside the scope of the block). Thus, __block don't get retained by blocks.

But, now you can run into unforeseen problems if you try to use this block in certain ways. For instance, if you decide to delay the invocation of this block somehow, and self has been deallocated by the time you execute that block, your program will crash, since you're sending a message to a deallocated object. What you need then is a weak reference, which is not provided out-of-the-box in the non-garbage-collected environment!

One solution is to use MAZeroingWeakRef to wrap your block; this will zero out the pointer so that you'll just end up sending messages to nil should you attempt to message self after self has been deallocated:

MAZeroingWeakRef *ref = [MAZeroingWeakRef refWithTarget:self];
self.block = ^{
  [ref.target something];
};

I've also implemented a weak reference wrapper in Objective-C++, which provides the benefit of a more lightweight syntax:

js::weak_ref<SomeClass> ref = self;
self.block = ^{
  [ref something];
};

Because js::weak_ref is a class template, you'll get handy strong-typing (that is, you'll get warnings at compile-time if you try to send the reference a message which it doesn't appear to respond to). But Mike's MAZeroingWeakReference is a lot more mature than mine, so I'd suggest using his unless you want to get your hands dirty.

To read more about issues with __block and the use-case for weak references, read Avoiding retain cycles with blocks, a right way and Jonathan Rentzsch's response.

Downloading normal image Vs retina device image (2x)

7 votes

When we need to download an image from some URL and show it on two kinds of devices -- Retina (with 2x image) and regular device -- Should we have two different image URLs to handle this?

For the images in the resource bundle we are keeping both xyz.png and xyz@2x.png and its working fine.

For images we are fetching from server do we need to have separate image URLs for both these kind of images and cache them locally with the same naming convention (xyz.png and xyz@2x.png)?

Please throw some light here.

You can check if the device has a high-resolution retina display and based on that download a different image. Don't bother for photos and stuff that you'd scale anyway for interface size.
You can create the scaled version of the downloaded image with

UIImage *image = //download...
image=[UIImage imageWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];

Keep in mind that a scaled 100x100 image will become a 50x50 points image (with 2.0 scale).

Check first if you have a retina display

if([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
    BOOL retina = [[UIScreen mainScreen] scale] == 2.0 ? YES : NO;

If you have an IBOutlet, but not a property, is it retained or not?

7 votes

I find the documentation on this issue to be unclear:

Say you are working with iOS (NOT the Mac case, no need to mention the differences). Say it is strictly 4.0+ (no need to mention differences in old OS). Say we are loading the NIB strictly automatically.

Say you have a UIViewController, BigView. Say there are a dozen so-called "top-level" items in the NIB file .. could be custom controls, images, or anything else.

Say you are definitely going to explicitly create and then get rid of BigView a number of times during the app's run. So:

For one of these top-level items in the NIB, there are three possibilities:

(1) You do not have any sort of IBOutlet for it, at all.

(2) You do have a connected IBOutlet - but not a property.

(3) You do have a connected IBOutlet property (to avoid confusion, we'll say a retain property).

So what happens to the item when BigView is released?

In the case of (3) it seems clear that you must release explicitly. If you do not, it will hang around after the view is gone. No problem.

In the case of (1) I assume (but can anyone actually confirm?) that the item will be released when BigView is gone.

In the case of (2) it's not clear what happens.......

Looking at the well-known reference link: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html it is very dubious:

"In iOS, the nib-loading code uses the setValue:forKey: method to reconnect each outlet. That method similarly looks for an appropriate accessor method and [SO WHAT HAPPENS IF THERE ISN'T ONE?? TELL US APPLE...] falls back on other means when that fails...[GOOD GRIEF!]"

And check out this documentation: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html and scroll down to "Nib Object Retention"

So ...

"Objects in the nib file are created with a retain count of 1 and then autoreleased" Fantastic..

But wait! Read on a few words...

however, ... which uses the available setter method or retains the object by default if no setter method is available

What are they talking about?

Do they mean that if no setter is available (ivar, but no property), that it is AGAIN RETAINED (other than the "retain" they just mention in the previous clause) --- or, are they just repeating themselves, i.e. the "retains the object by default" is the same "retain" they were talking about immediately previously ("created with a retain count of 1 and then autoreleased").

And why would they even mention the autorelease if that's not what happens?

Indeed -- if anyone actually specifically knows the answer to this question ...... how do you know?!? Did you ask DTS, or through testing, or? I suggest, the key documentation (just pasted in) is aggressively unclear.

Again - if you have an IBOutlet, but not a property, connected to a "top-level" object .. are you responsible for releasing it? Is it retained? in that situation?

For that matter .... merely in situation (1) is it absolutely the case that the thingy will be released when BigView goes away? I would certainly assume this is the case, but who knows?

The question is what happens if you DO use an IBOutlet iVar, but NOT a property...

I've foolishly never thought about this before / assumed too much, does anyone have the decisive answer? Cheers!!


For the record I have made a test project.

In fact (surprisingly to me) the mere act of connecting an IB element to an IBOutlet in fact apparently adds one retain.

(I can only assume from the shoddy docu, in that situation you get specifically: Retain, Autorelease, Retain - leading to one retain on balance.)

So, that's the answer.

I will post the demo project. I also direct any readers to Jonah's answer below which flawlessly explains the behavior of setValue:forKey: Cheers

I don't see what causes so much confusion, I think the "Nib Object Retention" documentation explains exactly what happens. Let's break it down and walk through what happens:

Objects in the nib file are created with a retain count of 1 and then autoreleased.

ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease];

As it rebuilds the object hierarchy, however, UIKit reestablishes connections between the objects using the setValue:forKey: method,

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];

which uses the available setter method or retains the object by default if no setter method is available.

The default behavior of -setValue:forKey: in iOS is roughly

//lazy pseudocode
if ([self respondsToSelector:@selector(@"setKeyName:")]) {
  [self setKeyName:value];
}
else {
  object_setIvar(self, _keyName, [value retain]);
}

See the key-value programming guide for even more detail. Unless your file's owner object overrides -setValue:forKey: (or +accessInstanceVariablesDirectly and -setValue:forUndefinedKey: ) expect object ownership to be managed as above.


If you define outlets for nib-file objects, you should always define a setter method (or declared property) for accessing that outlet. Setter methods for outlets should retain their values, and setter methods for outlets containing top-level objects must retain their values to prevent them from being deallocated.

Allowing nib loading to set ivar directly to externally retained objects is confusing. Don't do that. Provide setter methods for your outlets so the ownership of the loaded object is clear.


If you do not store the top-level objects in outlets, you must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.

Objects not connected to outlets have been autoreleased. Retain them or the array returned from -loadNibNamed:owner:options: if you are going to try to access them later.

why does this different "addSubView" code cause differences in behavior

7 votes

Why does changing the below code from the Old to New entry fix the following problem.

Code:

  // OLD Entry - Did not work
  //[self.window addSubview:navigationController.view];

  // NEW Entry - Fixed it
  self.window.rootViewController = self.navigationController;

Problem when I use Old Code:

  • I'm using a UINavigationController and have a "mainView" UITableViewController and then a 2nd level view I push onto the stack, let's call it "detailedView" UITableViewController.

  • Navigating normally back and forward from main to details works fine

  • BUT when automatically launch on startup into the 2nd view (as I save state) I get to the 2nd view OK, however the TOOLBAR BUTTONS do NOT appear at the bottom of the 2nd view in this case. When I go back to main page (via UINavigationController standard arrangements), and then then select the row in the UITableView, and go back into the same view again the toolbar items appear fine.

  • Couldn't track this down but finally through trial and error I noted this change in code (see above) in the appDelegate (of all places) seems to fix the issue.

Any ideas?

EDIT: For completeness here is the full method

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
    NSManagedObjectContext *context = [self managedObjectContext];
    if (!context) {
        abort();  // TODO: Do better job here than abort
    }
    rootViewController.managedObjectContext = context;
     self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

EDIT 2: Oh, I do have a NIB file and have the root view controller/window setup in interface builder - so I'm wondering if I'm mixing a NIB and programmatic approach up here perhaps which might cause problems?

EDIT 3: Also noted that the following didFinishLaunchingWithOptions code worked when I added the "self.window.rootViewController = self.navigationController" line. That is without this line (which is what the coredatabooks example does) I get the issue.

RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
    rootViewController.managedObjectContext = self.managedObjectContext;
    self.window.rootViewController = self.navigationController;  // WORKS WHEN I ADD THIS LINE IN FOR SOME REASON???

    // Configure and show the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];

return YES;

The difference between the two methods is that one triggers the view lifecycle methods the other dose not.

I.e. setting window.rootViewController will cause the old view controller to receive the messages: viewDidDissaper viewWillDissapear etc.. while the new view controller will receive the viewWillApear, viewDidAppear etc..

addSubview: does not do this.

Does this help?

EDIT:

Reading your post in detail it looks like you are adding the buttons programatically on the viewDidAppear method of the detail view.

The rootViewController property of UIWindow was added as of 4.0. The documentation does not explicitly mention that it will trigger the view life cycle methods, i found this out through trail and error like yourself. (perhaps someone can raise an issue against the apple documentation).

If you need to be backwards compatible for 3.x you can this a custom UIWindow subclass. My code is below. use window.djRootViewController = yourViewController instead of window.rootViewController. It is designed for use in Interface builder.

#import <UIKit/UIKit.h>

@interface DJWindow : UIWindow {

    UINavigationController* m_navigationController;
}

@property (nonatomic, retain) UIViewController* djRootViewController;

@end




#import "DJWindow.h"

@interface DJWindow()

- (void) customInit;

@end


@implementation DJWindow


- (id) initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self customInit];
    }
    return self;
}


- (void) customInit {
    m_navigationController = [[UINavigationController alloc] init];

    m_navigationController.navigationBarHidden = YES;

    [self addSubview:m_navigationController.view];
}

- (void) setRootViewController:(UIViewController *)rootViewController {
    NSLog(@"ERROR, do not set the rootViewController property, use djRootViewController instead");
}

- (void) setDjRootViewController:(UIViewController *)djRootViewController {

    if (djRootViewController == nil) {
        [m_navigationController setViewControllers:nil];
    } else {
        NSArray* vcArray = [NSArray arrayWithObject:djRootViewController];
        [m_navigationController setViewControllers:vcArray];
    }
}

- (UIViewController*) djRootViewController {

    return m_navigationController.visibleViewController;
}

- (void)dealloc
{
    [m_navigationController release];
    [super dealloc];
}


@end

iPad: new 4/5 finger multitasking gestures - when is the app's screenshot taken?

7 votes

When my app resigns activation it covers the current view with a black view to prevent iOS from taking a screenshot of the potentially sensitive document being shown.

When pushing the app to background this works fine. The screenshot is taken AFTER didEnterBackground. Using multitasking gestures to switch back shows the black view.

However with the new 4/5 finger gestures if you swipe left or right, first "resign activation" is triggered and then "did enter background" but the screenshot seems to be taken BEFORE these events. How to prevent it in that case?

If I understand correctly, you're trying to avoid this problem:

http://software-security.sans.org/blog/2011/01/14/whats-in-your-ios-image-cache-backgrounding-snapshot/

And the issue is that the behavior doesn't match what Apple documents here:

http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/CoreApplication/CoreApplication.html#//apple_ref/doc/uid/TP40007072-CH3-SW21

If that's true, then this definitely sounds like a bug -- but you do realize the gesture you mentioned is apparently a developer feature that's not available to the public (and under NDA)?

I'd do the following:

  1. Sumbit a bug report - http://bugreport.apple.com/

  2. Ask on the Apple Developer Forums (and include the bug number). People can speak freely there, and it's possible that an Apple developer will respond or at least notice your post (and hopefully prioritize the bug).

  3. Finally, if you really want a response from Apple, then problems like this are a perfect use for your technical support incidents. You get 2 of these per year included with your ADC membership: http://developer.apple.com/support/resources/technical-support.html

Genetic Algorithm optimization - using the -O3 flag.

6 votes

Working on a problem that requires a GA. I have all of that working and spent quite a bit of time trimming the fat and optimizing the code before resorting to compiler optimization. Because the GA runs as a result of user input it has to find a solution within a reasonable period of time, otherwise the UI stalls and it just won't play well at all. I got this binary GA solving a 27 variable problem in about 0.1s on an iPhone 3GS.

In order to achieve this level of performance the entire GA was coded in C, not Objective-C.

In a search for a further reduction of run time I was considering the idea of using the "-O3" optimization switch only for the solver module. I tried it and it cut run time nearly in half.

Should I be concerned about any gotcha's by setting optimization to "-O3"? Keep in mind that I am doing this at the file level and not for the entire project.

-O3 flag will make the code work in the same way as before (only faster), as long as you don't do any tricky stuff that is unsafe or otherwise dependant on what the compiler does to it.

Also, as suggested in the comments, it might be a good idea to let the computation run in a separate thread to prevent the UI from locking up. That also gives you the flexibility to make the computation more expensive, or to display a progress bar, or whatever.


Tricky stuff

Optimisation will produce unexpected results if you try to access stuff on the stack directly, or move the stack pointer somewhere else, or if you do something inherently illegal, like forget to initialise a variable (some compilers (MinGW) will set them to 0).

E.g.

int main() {
    int array[10];
    array[-2] = 13; // some negative value might get the return address
}

Some other tricky stuff involves the optimiser stuffing up by itself. Here's an example of when -O3 completely breaks the code.

how should I defensively code for possible core data file corruption or loading issues?

6 votes

I'm using Core Data in my iPhone application which is fine.

I'm concerned about what approach I should be taking if there is ever an error loading the core data data into my application (or saving it for that matter). In particular a possible situation (not sure what the odds are of this occuring but better to be safe than sorry) where your application can't function at all because it can't load it's data, and restarting the application brings it back to the same please.

Question - what do people typically do if trying to handle this situation? What approach in other words? The only ones that jump to mind so far are:

  1. Build in an error handler that prompts the user re whether they want to delete their data and start again so to speak...I guess this assumes the iPhone will report the problem to the program properly as an error

  2. Suggest to the user they may have to delete the application and reinstall (less work)

  3. Other? Not sure if there are any "clean up" or "repair" code/tips that are possible, or whether one should even think about trying this anyway....

thanks

PS. I haven't got to the point of understanding/dealing with core data migrations for upgrades of the applicaiton where the core data schema has changed. Perhaps this is just another possible situation to which the above questions are still valid...Or not sure whether the approach that one takes within the code (and with user messages) will depend on whether it's a migration error, or a separate error.

Better safe than sorry is fine but don't burn a lot of time on this. Core Data corruption is extremely rare. Even repeatedly crashing during saves seldom causes problems.

In any case, the only way to deal with a corrupt store is to delete it. You will probably want to set some kind of flag to delete the file when the app shuts down. Upon detection of the corrupt file, give the user the option to delete the store and restart the app.

Is a private synthesized property an oxymoron?

6 votes

After going through a beginner's iPhone developer book and reading sample code online, I've noticed that most Objective C programmers synthesize nearly every instance variable. Some variables are convenient to snythesize, but most should not when honoring the object oriented principle of encapsulation. The worst are synthetized properties marked as private. A C++ programmer trying to use someone else's code will read the public fields and methods in the header file. They will skip the private variables. This C++ programmer will not know that you intended the private properties to be used in some meaningful way.

Take a look at this sample template on lazy table image loading provided by Apple:

Header

@interface ParseOperation : NSOperation <NSXMLParserDelegate>

{
@private
    id <ParseOperationDelegate> delegate;
    NSData          *dataToParse;
    NSMutableArray  *workingArray;
    AppRecord       *workingEntry;
    NSMutableString *workingPropertyString;
    NSArray         *elementsToParse;
    BOOL            storingCharacterData;
}

Source

@interface ParseOperation ()
@property (nonatomic, assign) id <ParseOperationDelegate> delegate;
@property (nonatomic, retain) NSData *dataToParse;
@property (nonatomic, retain) NSMutableArray *workingArray;
@property (nonatomic, retain) AppRecord *workingEntry;
@property (nonatomic, retain) NSMutableString *workingPropertyString;
@property (nonatomic, retain) NSArray *elementsToParse;
@property (nonatomic, assign) BOOL storingCharacterData;
@end

@implementation ParseOperation
@synthesize delegate, dataToParse, workingArray, workingEntry, workingPropertyString, elementsToParse, storingCharacterData;

Now I know this is not C++ and we shouldn't assume all C++ practices should be honored in Objective C. But Objective C should have good reasons to stray away from general programming practices.

  1. Why are all the private ivars synthesized? When you look at the project as a whole, only NSMutableArray *workingArray is used by outside classes. So none of the other ivars should have setters and getters.
  2. Why are very sensitive ivars synthesized? For one, now that id delegate has a setter, the user of this object can switch the delegate in middle of the XML parsing, something that doesn't make sense. Also, NSData *dataToParse is raw XML data retrieved from the network. Now that it has a setter, the user of this object can corrupt the data.
  3. What's the point of marking everything private in the header? Since all ivars are are synthesized to have getters/setters, they are effectively public. You can set them to anything you want and you can get their value whenever you want.

I follow the idiom modeled by this example in many of my classes, so I can try to explain my own justification for this practice.

The properties in this example are declared in a class extension in the .m file. This makes them effectively private. Any attempt to access these properties from another class will cause a "Property not found" error upon compilation.

For developers coming from other languages, it may seem strange to synthesize getters and setters for private instance variables. Indeed, there is only one reason why I do this. When used consistently, synthesized properties can simplify memory management and help avoid careless mistakes that can lead to bugs. Here are a couple of examples:

Consider this:

self.workingPropertyString = [NSMutableString string];

versus this:

workingPropertyString = [[NSMutableString string] retain];

Many developers would claim that these two assignments are functionally equivalent, but there's an important difference. The second assignment leaks memory if workingPropertyString was already pointing at a retained object. To write code functionally equivalent to the synthesized setter, you'd have to do something like this:

NSMutableString *newString = [NSMutableString string];
if (workingPropertyString != newString) {
    [workingPropertyString release];
    workingPropertyString = [newString retain];
}

This code avoids leaking any existing object that the instance variable may be pointing to, and it safely handles the possibility that you may be re-assigning the same object to the instance variable. The synthesized setter does all of this for you.

Of course we can see that (workingPropertyString != newString) will always be true in this case, so we could simplify this particular assignment. In fact in most cases you can probably get away with a simple direct assignment to an instance variable, but of course it's the exceptional cases that tend to create the most bugs. I prefer to play it safe and set all my object instance variables through synthesized setters. All my instance object assignments are simple one-liners that look like this:

self.foo = [Foo fooWithTitle:@"The Foo"];

or this:

self.foo = [[[Foo alloc] initWithTitle:@"The Foo"] autorelease];

This simplicity and consistency gives my feeble brain less stuff to think about. As a result I almost never have bugs related to memory management. (I'm aware that the autorelease idiom could theoretically consume excessive memory in a tight loop, but I have yet to encounter that issue in practice. If I ever do, it's a simple case to optimize.)

One other thing I like about this practice is that my dealloc methods all look like this:

- (void)dealloc {
    self.delegate = nil;
    self.dataToParse = nil;
    self.workingArray = nil;
    self.workingEntry = nil;
    self.workingPropertyString = nil;
    self.elementsToParse = nil;
    [super dealloc];
}

EDIT: Daniel Dickison pointed out some risks to using accessors in dealloc that I hadn't considered. See the comments.

where every object property is simply set to nil. This simultaneously releases each retained property while setting it to nil to avoid certain crashes due to EXC_BAD_ACCESS.

Note that I've set self.delegate = nil; even though that property was declared as (nonatomic, assign). This assignment wasn't strictly necessary. In fact, I could do away with properties for my (nonatomic, assign) objects altogether, but again I've found that applying this idiom consistently across all my instance variables gives my brain less to think about, and further reduces the chance that I'll create a bug through some careless mistake. If necessary I can simply flip a property from (nonatomic, assign) to (nonatomic, retain) without having to touch any memory management code. I like that.

One could also use consistency as an argument for synthesizing properties for private scalar variables, as your example has done in the case of BOOL storingCharacterData;. This practice ensures that every instance variable assignment will look like self.foo = bar;. I don't usually bother to create private scalar properties myself, but I can see some justification for this practice.

iPhone - How do I know if the vibrate is on or off for iOS?

5 votes

Hello,

Do you know how I may know if the iPhone is on vibrate mode ? I don't find anything about this on the Web... Too tired to see ?

I want to display an icon in the app so that the user can know looking at it if the phone is on vibrate mode or not. Tha app has also different behaviours depending on if the user wants to be disturbed (vibrate off) or not (vibrate on).

Thank you.

You should be able to achieve this using:

#import "AudioToolbox/AudioToolbox.h"

- (void) ifSilentModeThenShowIcon
{
   CFStringRef state;
   UInt32 propertySize = sizeof(CFStringRef);
   AudioSessionInitialize(NULL, NULL, NULL, NULL);
   AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);

   if(CFStringGetLength(state) == 0)
   { 
     // phone's ringer is off so put
     // some icon showing code here
   }
}

Source

play two video in iPhone simultaneously.

5 votes

Hi All,

I want to play two video in iPhone simultaneously.

There are two way to play video in iphone, One is use AVQueuePlayer. but in this controller I don't get how get the video playing is completed and how to restart video again.

Another way is MPMoviePlayerController . but in this controller I don't get how to seek video at particular time and also it is not able to play two video simultaneously as the AVQueuePlayer is able to play.

as a solution i am using AVQueuePlayer to play video and but can any one help me to restart video and get method to detect end point of the video. or know any other api to so this

Thanks in advance.

Hi ,

I have found the solution to play two video . You can use AVQueuePlayer to play video. Using this controller you can play two video at the same time .

Requesting iPhone location whilst in background?

5 votes

Simple question ... I have an application that records a users location at 30second intervals (using an NSTimer) it works perfectly until the application goes "inactive" and the NStimer stops. As a consequence I am looking for options to maintain my location interval (30secs) whilst still being able to record fairly accurate location data (within 100m accuracy).

  • Option_001, Brute Force: Let CLLocationManager, startUpdatingLocation run all the time using UIBackgroundModes = "location". Not recommended, drains battery. Regularity upon request, Accuracy approx. 10-65m. Might just be the only realistic option.

  • Option_002, SLC: I could use Significant Location Change but the frequency of location updates is pretty poor (not to mention accuracy). This is particularly true if the application is running in a rural or wilderness area with limited numbers of cell towers. Regularity unknown, Accuracy approx. 500m

  • Option_003, Hybrid: I could use Significant Location Change (SLC) in the background as an indicator of "significant" movement and then request an GPS location based on kCLLocationAccuracyBest. This would work but the SLC events are not going to arrive at anywhere near 30second intervals (particularly when walking). Regularity unknown, Accuracy approx. 10-50m.

  • Option_004, Something else? any ideas would be much appreciated.


NOTE: I thought I had this working because when you press [LOCK] on an iPhone (connected via USB) applicationWillResignActive is called but NSTimers do not stop. If you try the same with the iPhone un-connected (i.e. as the phone would be in normal use) the NSTimers stop almost immediately after applicationWillResignActive is called.

First of all, don't use a timer to update the user location. Approach it from the other end: check, when a new location is received, the interval since the last "recording" and decide if you want to record the new location or now.

Also, this will get around your "inactive" state problem. Just enable background location services. Info.plist > Required background modes > App registers for location updates

Whilst in background, when a new location is received, your app will go in a "background active" state that will allow enough time to make an API call and push the new location.

In a sentence, you need to design this app to work well with the new background modes.

Note: this solution won't work for iOS3.x