Best ios questions in November 2011

iOS: what's the fastest, most performant way to make a screenshot programatically?

14 votes

in my iPad app, I'd like to make a screenshot of a UIView taking a big part of the screen. Unfortunately, the subviews are pretty deeply nested, so it takes to long to make the screenshot and animate a page curling afterwards.

Is there a faster way than the "usual" one?

UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();

If possible, I'd like to avoid caching or restructuring my view.

Thanks a lot for your help!

I've found the answer for your question in the Technical Q&A of iOS Developer Library, so here it goes:

Every UIWindow (inherited from UIView) and UIView is backed by a CALayer. The CALayer/-renderInContext: method lets you render a layer and its sublayers to a graphics context. So, to grab a snapshot of the entire screen, you can iterate through each window on the screen and render its layer hierarchy to a destination context. Once finished you can get the screenshot image via the UIGraphicsGetImageFromCurrentImageContext function, as shown below.

To use Core Animation APIs, you need to add the QuartzCore framework in your Xcode project and include the QuartzCore header as shown in the following listing:


Listing 1: Include the QuartzCore header

#import <QuartzCore/QuartzCore.h>

Listing 2: Get a screenshot image

- (UIImage*)screenshot 
{
    // Create a graphics context with the target size
    // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
    // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
    CGSize imageSize = [[UIScreen mainScreen] bounds].size;
    if (NULL != UIGraphicsBeginImageContextWithOptions)
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    else
        UIGraphicsBeginImageContext(imageSize);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Iterate over every window from back to front
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
    {
        if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
        {
            // -renderInContext: renders in the coordinate space of the layer,
            // so we must first apply the layer's geometry to the graphics context
            CGContextSaveGState(context);
            // Center the context around the window's anchor point
            CGContextTranslateCTM(context, [window center].x, [window center].y);
            // Apply the window's transform about the anchor point
            CGContextConcatCTM(context, [window transform]);
            // Offset by the portion of the bounds left of and above the anchor point
            CGContextTranslateCTM(context,
                                  -[window bounds].size.width * [[window layer] anchorPoint].x,
                                  -[window bounds].size.height * [[window layer] anchorPoint].y);

            // Render the layer hierarchy to the current context
            [[window layer] renderInContext:context];

            // Restore the context
            CGContextRestoreGState(context);
        }
    }

    // Retrieve the screenshot image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}

Hope this helps you.

Disadvantages of Objective-C++?

12 votes

I'm writing a large project for iOS in Objective-C++. I'm mainly using Objective-C for the UI and other Apple APIs, and C++ for internal audio processing and other information handling. I was wondering about the drawbacks of mixing Objective-C and C++ freely.

Of course, mixing two object models has its inherent limitations and potential for messiness and confusion. I'm more curious about how using Objective-C++ will affect the compilation process, syntactic pitfalls I might run into, problems with readability and how I might avoid those, etc. I'm interested to hear what your experiences with Objective-C++ have been like and tips you might have for approaching this.

ObjC++ is extremely powerful - you can select and mix the features you need for your problems and interface with C, ObjC, and C++ all at the same time. I've been using it for many years. There are of course, a few caveats, and it's good to be aware of them so you can minimize the issues you might encounter:

Compilation

The compilation times are much higher than ObjC or C++ when you begin creating nontrivial programs.

There are a few common approaches to declaring your C++ types in ObjC types:

  • Opaque types
  • Forward Declarations
  • Forward Declarations with smart pointers
  • By value

I'll just gloss over this, as it is inferred from the OP that you are familiar with both languages. As well, this is one of the more publicly written about introductory topics on ObjC++.

Given the C++ type:

class t_thing { public: int a; };

You have a number of ways to declare your ivars:

Opaque type:

@interface MONClass : NSObject { void* thing; } @end

This should be avoided. It's not good to erase type safety. The two forward options will introduce type safety.

This variant is compatible with ObjC translations.

Forward Declaration:

class t_thing;
@interface MONClass : NSObject { t_thing* thing; } @end

This is better than an opaque type, but the smart pointer is even better - pretty obvious if you are used to writing modern C++.

This variant is compatible with ObjC translations as long as your C++ types are in the global namespace.

Forward Declaration using smart pointers:

class t_thing;
@interface MONClass : NSObject { t_smart_pointer<t_thing> thing; } @end

This one is the best if you intend to set up translation firewalls (e.g. use PIMPL and forwards to reduce dependencies). As well, the ObjC object is already going through locking and allocations, so it's not a bad point to allocate a C++ type. If you have several declarations, you may prefer to create a wrapper type for your implementation to reduce individual allocations.

This variant is not compatible with ObjC translations.

This is a good time to remind you that there is a compiler option with ObjC++ that you should enable: GCC_OBJC_CALL_CXX_CDTORS. What happens when this flag is set? The compiler produces hidden objc methods which invoke your C++ ivars' constructors and destructors. If you use GCC_OBJC_CALL_CXX_CDTORS your C++ ivars must be default constructible. If you do not enable this flag, you must manually construct and destruct your ivars perfectly - if you construct it twice or do not override an initializer of the subclass, then you are facing UB.

By value:

#include "thing.hpp"    
@interface MONClass : NSObject { t_thing thing; } @end

Highest dependency. This is (in general) the route I chose, and I have some regrets about that. I've just moved things over to use more C++ and use composition with smart pointers (outlined above) to reduce dependency.

This variant is not compatible with ObjC translations.

One other thing about the modern ObjC compilers: The compiler lays out your C++ types' ivars/structure in the binary. Believe it or not, this can consume a lot of binary space.

The point here is that there are multiple forms the program can take. You can mix these techniques to reduce dependency, and this is one of the best places to introduce dependency firewalls because ObjC is very dynamic (its methods must be exported in one translation), and object creation requires allocations, locks, introduction into the reference counting system - initialization time for a single object is already relatively high, and the implementation will always be hidden.

If much of your program is still in ObjC and you want to keep it that way, then you will need to resort to forwards of types which are declared in the global namespace or opaque base types which you vend specializations through an object factory. Personally, I just use so much C++ that this was not an ideal option, and wrapping implementations in global types quickly became tiresome.

Meanwhile, since compilation times are high, the inverse is true: If you can keep significant portions of your implementation as C++, then you will save a lot of compilation time. For this reason and ARC (below) you can gain a lot by keeping your primitive Apple types as CF types where possible, so you can continue building C++ programs without the ObjC extensions.

Syntax

I rarely have problems but I keep my C++ classes quite strict:

  • I prohibit copy and assignment by default.
  • I rarely declare customized operators for C++ types.

If you're awesome at C++, then you could avoid this problem, but I prefer the compiler to catch silly mistakes I make.

One evident problem is C++ scope resolution within an ObjC message send. This requires a space:

[obj setValue:::func(a)]; // << bad
[obj setValue: ::func(a)]; // << good

Readability

One problem I have encountered is that I have never found a code formatter that supports the ObjC++ syntax well.

ObjC Messaging

  • ObjC Messaging and return by value: You need to check before messaging nil when returning C++ types by value. If the object you message is nil, then the result will be zeroed memory on the modern runtimes (x86_64 and iOS). If you use that instance, it is undefined behaviour.

  • ObjC Messaging and return by reference: You need to check before messaging nil when returning C++ types by reference. If the object you message is nil, then the result will be undefined behaviour (reference to 0/NULL).

To overcome the ObjC Messaging issues, I typically use a form like this:

- (bool)selector:(std::string&)outValue;

where the return value is false for some internal error, and true for success.

then you can safely write:

if (![obj selector:outString]) { /* bail here */ }

Miscellanea

  • ARC Compatibility: ObjC++ is not good for ARC. The primary reason is that ARC does not follow through mixed object models. Example: If you try to put a ObjC member into a C++ type, the compiler will reject the program under ARC. This is not really an issue because MRC is dead simple with ObjC++ (assuming you also use SBRM), but it may be a concern for the lifetime of your program.

  • Synthesized Properties: You will have to define your properties for C++ types.

  • External Tools: Beyond Xcode's toolset, there are few programs that handle or recognize ObjC++ well. Text editors, IDEs, utilities.

  • Apple's Tools: Within Xcode's utilities, Xcode's support for ObjC++ is a bit low. Refactoring (unavailable), navigation (improved with clang parser), outlining (is rather primitive), ObjC++ can disrupt IB's utilities, project upgrading is often not supported.

Invalid result returned from the software lookup service

12 votes

I tried to submit an iOS app via XCode organizer, but it failed right after authentication and organizer said "Invalid result returned from the software lookup service".

How can I solve this problem?

Check that your app status is "Waiting for Upload" in iTunes Connect. You can change the status to press "Ready to Upload Binary" blue button.

Why are iOS animations slow the first time they are run?

11 votes

It seems to me that the first time I run an animation (animating the frame of a UIView, or the position of a CALayer, etc) it is quite choppy, and subsequent animations are smooth.

What would be causing this, and is there any way to pre-cache the animation?

Note: this question is quite similar to this one: UIImageView animations lag at first run, but UIImages are not being used in my animations.

Assuming you are using [UIImage imageNamed: @"herp.png"] the image will be cached. If the image is drawn a lot it will be unpacked into memory, else it will do a lazy load of the image and cause a stutter.

Animate change of view controllers without using navigation controller stack, subviews or modal controllers?

11 votes

Navigation controllers have view controller stacks to manage, and limited animation transitions.

Adding a view controller as a sub-view to an existing view controller requires passing events to the sub-view controller, which is a pain to manage, loaded with little annoyances and in general feels like a bad hack when implementing (Apple also recommends against doing this).

Presenting a modal view controller again places a view controller on top of another, and while it doesn't have the event passing problems described above, it doesn't really 'swap' the view controller, it stacks it.

Storyboards are limited to iOS 5, and are almost ideal, but cannot be used in all projects.

Can someone present a SOLID CODE EXAMPLE on a way to change view controllers without the above limitations and allows for animated transitions between them?

A close example, but no animation: How to use multiple iOS custom view controllers without a navigation controller

Edit: Nav Controller use is fine, but there needs to be animated transition styles (not simply the slide effects) the view controller being shown needs to be swapped completely (not stacked). If the second view controller must remove another view controller from the stack, then it's not encapsulated enough.

Edit 2: iOS 4 should be the base OS for this question, I should have clarified that when mentioning storyboards (above).

EDIT: New answer that works in any orientation. The original answer only works when the interface is in portrait orientation. This is b/c view transition animations that replace a view w/ a different view must occur with views at least a level below the first view added to the window (e.g. window.rootViewController.view.anotherView).

I've implemented a simple container class I called TransitionController. You can find it at https://gist.github.com/1394947.

As an aside, I prefer the implementation in a separate class b/c it's easier to reuse. If you don't want that, you could simply implement the same logic directly in your app delegate eliminating the need for the TransitionController class. The logic you'd need would be the same however.

Use it as follows:

In your app delegate

// add a property for the TransitionController

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    MyViewController *vc = [[MyViewContoller alloc] init...];
    self.transitionController = [[TransitionController alloc] initWithViewController:vc];
    self.window.rootViewController = self.transitionController;
    [self.window makeKeyAndVisible];
    return YES;
}

To transition to a new view controller from any view controller

- (IBAction)flipToView
{
    anotherViewController *vc = [[AnotherViewController alloc] init...];
    MyAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    [appDelegate.transitionController transitionToViewController:vc withOptions:UIViewAnimationOptionTransitionFlipFromRight];
}

EDIT: Original Answer below - only works for portait orientation

I made the following assumptions for this example:

  1. You have a view controller assigned as the rootViewController of your window

  2. When you switch to a new view you want to replace the current viewController with the viewController owning the new view. At any time, only the current viewController is alive (e.g. alloc'ed).

The code can be easily modified to work differently, the key point is the animated transition and the single view controller. Make sure you don't retain a view controller anywhere outside of assigning it to window.rootViewController.

Code to animate transition in app delegate

- (void)transitionToViewController:(UIViewController *)viewController
                    withTransition:(UIViewAnimationOptions)transition
{
    [UIView transitionFromView:self.window.rootViewController.view
                        toView:viewController.view
                      duration:0.65f
                       options:transition
                    completion:^(BOOL finished){
                        self.window.rootViewController = viewController;
                    }];
}

Example use in a view controller

- (IBAction)flipToNextView
{
    AnotherViewController *anotherVC = [[AnotherVC alloc] init...];
    MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
    [appDelegate transitionToViewController:anotherVC
                             withTransition:UIViewAnimationOptionTransitionFlipFromRight];
}

How do I use regex to search ignoring certain characters with NSPredicate?

10 votes

In Hebrew, there are certain vowels that NSPredicate fails to ignore even when using the 'd' (diacritic insensitive) modifier in the predicate. I was told that the solution is to use regular expressions to do the search.

How do I take a search string and "use regex" to search hebrew text that contains vowels, ignoring those vowels?

Edit:

In other words, If I wanted to search the following text, disregarding dashes and asterisks, how would I do so using regex?

Example Text:

I w-en*t t-o the st*o*r*-e yes-ster*day.

Edit 2:

Essentially, I want to:

  1. Take an input string from a user
  2. Take a string to search
  3. Use a regex based on the user's search string to search for "contains" matches in the larger block of text. The regex should ignore vowels as shown above.

Edit 3:

Here's how I'm implementing my search:

//
//  The user updated the search text
//

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
shouldReloadTableForSearchString:(NSString *)searchString{

    NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];

    if (self.filteredArray == nil) {
        self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
    }

    [filteredArray removeAllObjects];

    NSPredicate *predicate;

    if (controller.searchBar.selectedScopeButtonIndex == 0) {
        predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", searchString];
    }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
        predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", searchString];            
    }else if (controller.searchBar.selectedScopeButtonIndex == 2){
        predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
    }else{
        predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", searchString,searchString,searchString];
    }

    for (Article *article in unfilteredResults) {

        if ([predicate evaluateWithObject:article]) {
            [self.filteredArray addObject:article];
        }

    }

    [unfilteredResults release];


    return YES;
}

Edit 4:

I am not required to use regex for this, was just advised to do so. If you have another way that works, go for it!

Edit 5:

I've modified my search to look like this:

NSInteger length = [searchString length];

NSString *vowelsAsRegex = @"[\\u5B0-\\u55C4]*";

NSMutableString *modifiedSearchString = [searchString mutableCopy];

for (int i = length; i > 0; i--) {
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}

if (controller.searchBar.selectedScopeButtonIndex == 0) {
            predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
        }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
            predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];            
        }else if (controller.searchBar.selectedScopeButtonIndex == 2){
            predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", modifiedSearchString];
        }else{
            predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
        }

for (Article *article in unfilteredResults) {
  if ([predicate evaluateWithObject:article]) {
    [self.filteredArray addObject:article];
  }          
 }

I'm still missing something here, what do I need to do to make this work?

Edit 6:

Okay, almost there. I need to make two more changes to be finished with this.

I need to be able to add other ranges of characters to the regex, which might appear instead of, or in addition to the character in the other set. I've trie changing the first range to this:

[\u05b0-\u05c, \u0591-\u05AF]?

Something tells me that this is incorrect.

Also, I need the rest of the regex to be case insensitive. What modifier do I need to use with the .* regex to make it case insensitive?

This answer picks up where the question left off. Please read that for context.

As it turns out, iOS can make regular expressions case insensitive using an Objective-C modifier to NSPredicate. All that's left is to combine the two ranges. I realized that they are actually two consecutive ranges. My final code looks like this:

NSInteger length = [searchString length];

NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?"; //Cantillation: \u0591-\u05AF Vowels: \u05b0-\u05c

NSMutableString *modifiedSearchString = [searchString mutableCopy];

for (int i = length; i > 0; i--) {
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}

if (controller.searchBar.selectedScopeButtonIndex == 0) {
  predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
}else if (controller.searchBar.selectedScopeButtonIndex == 1) {
    predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[c] %@", modifiedSearchString];            
}else if (controller.searchBar.selectedScopeButtonIndex == 2){
    predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[c] %@", modifiedSearchString];
}else{
    predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[c] %@) OR (dvarTorahTitle CONTAINS[c] %@) OR (dvarTorahContent CONTAINS[c] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
}

[modifiedSearchString release];

for (Article *article in unfilteredResults) {
  if ([predicate evaluateWithObject:article]) {
    [self.filteredArray addObject:article];
  }          
}

Note that the range portion of the regular expression repeats itself. This is because there can be both a cantillation mark and a vowel on a single letter. Now, I can search uppercase and lowercase English, and Hebrew with or without vowels and cantillation marks.

Awesome!

What iPhone developer 3rd party products and services do you use?

9 votes

What third party iPhone developer products and services do you use? This could include reporting services, frameworks, tools, etc. I ask because there's probably a lot of great stuff out there that I never even thought to look for.

As an example, and to get the ball rolling, here are some that I like:

Airbrake http://airbrake.io/
Get your iPhone apps to send in error reports, allowing you to discover bugs and prioritise fixing them.

Test Flight https://testflightapp.com/
Provides an easy way to send beta versions of your app to testers and clients.

Google Analytics for iOS http://code.google.com/mobile/analytics/docs/iphone/
An SDK to get your iPhone app to report usage to Google Analytics.

HockeyApp http://hockeyapp.net/
Reliable crash reporting for beta and live apps, including server side symbolication and crash grouping. Beta distribution and management.

Localytics http://localytics.com/
Live analytics for usage reporting.

QuincyKit http://quincykit.net/
Open Source crash reporting framework for Mac and iOS. Manages sending crash reports to a server. Client can be used with HockeyApp or its own open source server. (Available since 2009)

HockeyKit http://hockeykit.net/
Open source beta distribution framework for iOS and Android. Manages distribution beta versions easily, including in app updates. Client can be used with HockeyApp or its own open source server. (Available since August 2010)

PLCrashReporter http://code.google.com/p/plcrashreporter/
Collect crash reports reliably on iOS and Mac (not all CPU architectures on Mac yet fully supported). Is being used by QuincyKit and HockeyApp. (Available since 2009)

KIF https://github.com/square/KIF
Test framework for automated UI testing. Also helps testing regressions, memory issues, non reproducible crashes.

AFNetworking https://github.com/gowalla/AFNetworking/
Efficient networking framework

JSONKit https://github.com/johnezang/JSONKit
Very fast JSON framework, as of now the fastest out there.

AppSales-Mobile https://github.com/omz/AppSales-Mobile
Download and analyze iTunes Connect sales data for your apps.

Objective-C blocks and C++ objects

8 votes

I have a method that is being executed on a background thread. From that method I'm trying to dispatch_async a block on the main thread. The block uses a local C++ object which is supposed to be copy constructed according to the Apple reference. I'm getting a segmentation fault and from the trace I see that something very sketchy is going on. Here's the simplified version of my code.

struct A
{
    A() { printf("0x%08x: A::A()\n", this); }
    A(A const &that) { printf("0x%08x: A::A(A const &%p)\n", this, &that); }
    ~A() { printf("0x%08x: A::~A()\n", this); }
    void p() const { printf("0x%08x: A::p()\n", this); }
};

- (void)runs_on_a_background_thread
{
    A a;
    a.p();
    dispatch_async(dispatch_get_main_queue(), ^{
        printf("block begins\n");
        a.p();
        printf("block ends\n");
    });
}

And this is the output:

0xbfffc2af: A::A()
0xbfffc2af: A::p()
0xbfffc2a8: A::A(A const &0xbfffc2af)
0x057ae6b4: A::A(A const &0xbfffc2a8)
0xbfffc2a8: A::~A()
0xbfffc2af: A::~A()
0xbfffdfcf: A::A(A const &0x57ae6b4)
0xbfffdfcf: A::~A()
block begins
0xbfffdfcf: A::p()
block ends
0x057ae6b4: A::~A()

There are two things that I don't understand. The first one is why by the time it gets to 0xbfffdfcf: A::p() the destructor on that object has been called already.

The second thing I'm struggling with is why there are so many copy constructors being called. I expect one. That should happen when a copy of a is created to be captured by the block.

I'm using Xcode 3.2.5 with GCC. I experience the same behavior on the simulator and on the device.

I just tested this on LLVM 3.0.

0xb024ee18: A::A()
0xb024ee18: A::p()
0xb024ee04: A::A(A const &0xb024ee18)
0x06869364: A::A(A const &0xb024ee04)
0xb024ee04: A::~A()
0xb024ee18: A::~A()
block begins
0x06869364: A::p()
block ends
0x06869364: A::~A()

As you can see the destructors get called appropriately in this case, I'd chalk this up to a complier bug in the extremely outdated compiler you're using.

The copies in this instance seem inline with what I'd expect. The block copies the stack based object into the block when it gets captured. And then again when the block gets copied from the stack to the heap.

How do I access the compass in iOS?

7 votes

How do I access the iphone compass in Firemonkey?

Here's a howto video: http://blogs.embarcadero.com/ao/2011/10/13/39171
Full source code: http://cc.embarcadero.com/item/28536
And a (short) article: http://edn.embarcadero.com/article/41715

And here's source code for a compass component.
Have not tried it yet, but it should work.

unit Compass;

{Based on Anders Ohlsson Firemonkey Compass example}

{$IFDEF FPC}
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$ENDIF}

interface

uses
  SysUtils, Classes, FMX_Types
{$IFDEF FPC}
  , iPhoneAll
{$ENDIF}
  ;

type
  TUpdateEvent = TNotifyEvent;

  TiOSGPSCompass = class(TFmxObject)
  private
    FLatitude: Double;
    FLongitude: Double;
    FAltitude: Double;
    FHeading: Double;
    FOnUpdate: TUpdateEvent;
    UpdateNeeded: Boolean;
  protected
    procedure SetLatitude(value: Double);
    procedure SetLongitude(value: Double);
    procedure SetAltitude(value: Double);
    procedure SetHeading(value: Double);
    procedure Update;
  public
    constructor Create(AOwner: Classes.TComponent); override;
    destructor Destroy; override;
  published
    property Latitude: Double read FLatitude;
    property Longitude: Double read FLongitude;
    property Altitude: Double read FAltitude;
    property Heading: Double read FHeading;
    property OnUpdate: TUpdateEvent read FOnUpdate write FOnUpdate;
  end;

var
  MyGPSCompass: TiOSGPSCompass = nil;

procedure Register;

implementation

{$IFDEF FPC}
uses
  CoreLocation;
{$ENDIF}

{$IFDEF FPC}
type
  MyCLController = objcclass(NSObject)
    locationManager : CLLocationManager;
    procedure locationManager_didUpdateToLocation_fromLocation(manager: CLLocationManager; newLocation, oldLocation: CLLocation); message 'locationManager:didUpdateToLocation:fromLocation:';
    procedure locationManager_didUpdateHeading(manager: CLLocationManager; newHeading: CLHeading); message 'locationManager:didUpdateHeading:';
  end;

var
  Controller : MyCLController;
{$ENDIF}


{$IFDEF FPC}
procedure MyCLController.locationManager_didUpdateToLocation_fromLocation(manager: CLLocationManager; newLocation, oldLocation: CLLocation);
begin
  if Assigned(MyGPSCompass) then begin
    MyGPSCompass.SetLatitude(newLocation.coordinate.latitude);
    MyGPSCompass.SetLongitude(newLocation.coordinate.longitude);
    MyGPSCompass.SetAltitude(newLocation.altitude);
    MyGPSCompass.Update;
  end;
end;
{$ENDIF}

{$IFDEF FPC}
procedure MyCLController.locationManager_didUpdateHeading(manager: CLLocationManager; newHeading: CLHeading);
begin
  if Assigned(MyGPSCompass) then begin
    MyGPSCompass.FCompassHeading:= newHeading.magneticheading;
    MyGPSCompass.Update;
  end;
end;
{$ENDIF}

constructor TiOSGPSCompass.Create(AOwner: TComponent);
begin
  inherited;
  {$IFDEF FPC}
    Controller := MyCLController.alloc.init;
  Controller.locationManager := CLLocationManager.alloc.init;
    Controller.locationManager.setDelegate(Controller);
  Controller.locationManager.setDesiredAccuracy(kCLLocationAccuracyBestForNavigation);
    Controller.locationManager.startUpdatingLocation;
  Controller.locationManager.startUpdatingHeading;
  {$ENDIF}
  MyGPSCompass:= Self;
end;

destructor TiOSGPSCompass.Destroy;
begin
  {$IFDEF FPC}
  Controller.locationManager.release;
  Controller.release;
  {$ENDIF}
  inherited;
end;

procedure TiOSGPSCompass.SetLatitude(value: Double);
begin
  if (FLatitude <> value) then begin
    FLatitude:= value;
    UpdateNeeded:= True;
  end;
end;

procedure TiOSGPSCompass.SetLongitude(value: Double);
begin
  if (FLongitude <> value) then begin
    FLongitude:= value;
    UpdateNeeded:= True;
  end;
end;

procedure TiOSGPSCompass.SetAltitude(value: Double);
begin
  if (FAltitude <> value) then begin
    FAltitude:= value;
    UpdateNeeded:= True;
  end;
end;

procedure TiOSGPSCompass.SetHeading(value: Double);
begin
  if (FHeading <> value) then begin
    FHeading:= value;
    UpdateNeeded:= True;
  end;
end;

procedure TiOSGPSCompass.Update;
begin
  if (UpdateNeeded and Assigned(OnUpdate)) then OnUpdate(Self);
  UpdateNeeded:= False;
end;

procedure Register;
begin
  RegisterComponents('iOS', [TiOSGPSCompass]);
end;

end.

Can developers use iCloud in Windows apps?

7 votes

Developers can use Apple’s iCloud APIs to sync app data between different versions of their app on Mac OS X and iOS.

If a developer has a Windows version of their app, can this version also use iCloud to sync app data with versions of their app on Mac OS X and iOS?

Access to iCloud is controlled by Apple in such a way that each app that accesses it has to be signed and/or provided a key from Apple. That's the easiest way to put it without violating NDA, although the mechanism is not exactly "signing and keys".

At the moment Apple is only providing this for OS X and IOS apps, so effectively no - windows, web, and apps outside OS X and IOS are not supported at this time.

What are the different ways for calling my method on separate thread?

7 votes

I have some data calculation method (let it be "myMethod:"), and I want to move the call to another thread because I don't want to block my main UI functionality. So, started to do some research on how to call my method on another thread. As far as I see, currently, there are a lot of different ways for doing that. Here's a list:

a) using pure threads (available since iOS 2.0):

[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray];

b) using a simple shortcut (available since iOS 2.0). Available from inherited NSObject but the method belongs to NSThread class too:

[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];

c) using a new approach of Grand Central Dispatch queues (available since iOS 4.0):

dispatch_async(dispatch_get_global_queue(0, 0),
  ^ {
      [self myMethod:_myParamsArray];
    });

d) somehow, using some classes such as NSOperation, NSBlockOperation or NSOperationQueue, though not sure how exactly to do it (some example would be appreciated)

Currently, I have used case "b" but curious about pros and cons and other related suggestions on that.

Usually, you would prefer the GCD approach.

It's simpler when it comes to synchronization/locking than pure threads (NSThread - pthread), and it may be more accurate in a performance perspective.

When using pure threads, the problem is you may have performance issues, depending on the number of available cores/processors.

For instance, if you have only one core, creating many threads may slow down your application, because the CPU will spend most of its time switching from one thread to another, saving the stack, registers, etc.

On the other hand, if you have a lot of cores available, it may be nice to create a lot of different threads.

This is where GCD helps, as it manages this for you. It will create the appropriate number of threads, based on the available system resources, to guarantee an optimal utilization, and schedule your actions appropriately.

However, for that reason, tasks launched with GCD may not be real-time.

So if you REALLY needs that a detached task runs immediately, use an explicit threads. Otherwise, use GCD.

Hope this will help you : )

EDIT

A note about performSelectorInBackground: it simply creates a new thread. So there's basically no difference with the NSThread approach.

EDIT 2

NSOperation related stuff are a bit different. On Mac OS X, they are implemented using GCD since version 10.6. Previous versions uses threads.

On iOS, they are implemented using threads only.

Reference

All of this is very well explained in the Concurrency Programming Guide. It discusses the GCD and thread approaches, with a lot of details about the uses and implementations.

If you haven't read it already, you should take a look.

Performance hit from blending large quad

6 votes

I have a game which runs pretty well (55-60fps) on a retina display. I want to add a fullscreen overlay that blends with the existing scene. However, even when using a small texture, the performance hit is huge. Is there an optimization I can perform to make this useable?

If I use a 80x120 texture (the texture is rendered on the fly, which is why it's not square), I get 25-30FPS. If I make the texture smaller, performance increases, but quality is not acceptable. In general, though, the quality of the overlay is not very important (it's just lighting).

Renderer utilization is at 99%.

Even if I use a square texture from a file (.png), performance is bad.

This is how I create the texture:

    [EAGLContext setCurrentContext:context];

    // Create default framebuffer object.
    glGenFramebuffers(1, &lightFramebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);

    // Create color render buffer and allocate backing store.
    glGenRenderbuffers(1, &lightRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, LIGHT_WIDTH, LIGHT_HEIGHT);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, lightRenderbuffer);

    glGenTextures(1, &lightImage);
    glBindTexture(GL_TEXTURE_2D, lightImage);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LIGHT_WIDTH, LIGHT_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightImage, 0);

And here is the rendering...

/* Draw scene... */

glBlendFunc(GL_ONE, GL_ONE);


//Switch to offscreen texture buffer
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
glViewport(0, 0, LIGHT_WIDTH, LIGHT_HEIGHT);

glClearColor(ambientLight, ambientLight, ambientLight, ambientLight);
glClear(GL_COLOR_BUFFER_BIT);

/* Draw lights to texture... */

//Switch back to main frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);  

glBlendFunc(GL_DST_COLOR, GL_ZERO);

glBindTexture(GL_TEXTURE_2D, glview.lightImage);    

/* Set up drawing... */

glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0);

Here are some benchmarks I took when trying to narrow down the problem. 'No blend' means I glDisable(GL_BLEND) before I draw the quad. 'No buffer switching' means I don't switch back and forth from the offscreen buffer before drawing.

(Tests using a static 256x256 .png)
No blend, No buffer switching: 52FPS
Yes blend, No buffer switching: 29FPS //disabled the glClear, which would artificially speed up the rendering
No blend, Yes buffer switching: 29FPS
Yes blend, Yes buffer switching: 27FPS

Yes buffer switching, No drawing: 46FPS

Any help is appreciated. Thanks!

UPDATE

Instead of blending the whole lightmap afterward, I ended up writing a shader to do the work on the fly. Each fragment samples and blends from the lightmap (kind of like multitexturing). At first, the performance gain was minimal, but then I used a lowp sampler2d for the light map, and then I got around 45FPS.

Here's the fragment shader:

lowp vec4 texColor = texture2D(tex, texCoordsVarying);
lowp vec4 lightColor = texture2D(lightMap, worldPosVarying);
lightColor.rgb *= lightColor.a;
lightColor.a = 1.0;

gl_FragColor = texColor * color * lightColor;

Ok I think you've run up against the limitations of the hardware. Blending a screen-sized quad over the whole scene is probably a particularly bad case for the tile-based hardware. The PowerVR SGX (on the iPhone) is optimized for hidden surface removal, to avoid drawing things when not needed. It has low memory bandwidth because it's optimized for low power device.

So screen-sized blended quad is reading then writing every fragment on the screen. Ouch!

The glClear speed up is related - because you're telling GL you don't care about the contents of the backbuffer before rendering, which saves loading the previous contents into memory.

There's a very good overview of the iOS hardware here: http://www.imgtec.com/factsheets/SDK/POWERVR%20SGX.OpenGL%20ES%202.0%20Application%20Development%20Recommendations.1.1f.External.pdf

As for an actual solution - I would try directly rendering your overlay on the game scene.

For example, your render loop should look like:

[EAGLContext setCurrentContext:context];

// Set up game view port and render the game
InitGameViewPort();
GameRender();

// Change camera to 2d/orthographic, turn off depth write and compare
InitOverlayViewPort()

// Render overlay into same buffer 
OverlayRender()