Best iphone questions in September 2011

Where are the standard looking iOS controls\styles in Delphi XE2?

12 votes

We are currently in the process of evaluating Delphi XE2, and as you would expect I've started with FireMonkey as OS X and iOS development is of great interest. I've seen a couple of walkthrough's where people have created iOS apps using XE2 and I've managed to do the same, however the bread and butter of 'business applications' on an iPhone (which is how iOS support is being marketed) are buttons, lists, grids and connectivity (REST?).

Anyway, once you've created your iOS HD project the TButton initially looks green, whereas the TSpeedButton and TToolbar looks exactly like it should (blue gradient). The TToolbar doesnt have any way of adding buttons, presumably this is just a Panel, then?

Has anyone created styles for FM iOS HD apps, or do any of the wrappers allow direct creation of the standard iPhone controls?

I apologise if that sounds a little backwards given that I am attempting to evaluate using the trial version (which among other things doesnt provide the source, for obvious reasons!).

Thanks,

Ross

FireMonkey does not have standard iOS or OS X components. It draws all the components on its own, using a complicated set of layered sub-components, which are all editable with the FMX style editor in the IDE (or with a text editor outside the IDE).

So you can mimic the iOS or OS X components with the styles you get with the product or with your own custom styles. But to use the original UIKit/Cocoa Touch components, you'll have to use the FreePascal translations and conversions of the original Apple headers, and not FMX.

There is no designer for such UIs, unless you want to use Xcode 4.x. I don't know if FreePascal can load and use .xib files, though (although, why not? Probably just not automatically). You can, of course, create and place such components in code, at runtime.

So you either:

  • use FMX and design your own styles or modify the existing styles to your need, or
  • use Xcode and .xib files. Not sure how to do that with FreePascal.

FWIW, you can place any FMX component on any other FMX component (e.g. also a textbox on a button on an arcdial on a list item in a listbox), so it should be possible to place buttons on a toolbar. You probably have to take care of their alignment and arrangement, though, and probably also for their behaviour. Use a TLayout, Padding, Margins and alignment for that.

10 votes

I'm a beginner with GCD and CoreData, and I need your help to use CoreData with CGD, so that the UI is not locked while I add 40.000 records to CoreData.

I know that CD is not thread-safe, so I have to use another context, and then save the data and merge contexts, as far as I was able to understand from some articles.

What I could'n do yet, is put the pieces together.

So, in my code, I need your help on how to to that.

I have:

    {

    /*some other code*/

    for (NSDictionary *memberData in arrayWithResult){

    //get the Activities for this member
    NSArray *arrayWithMemberActivities = [activitiesDict objectForKey:[memberData objectForKey:@"MemberID"]];

    //create the Member, with the NSSet of Activities
    [Members createMemberWithDataFromServer:memberData
                         andActivitiesArray:arrayWithMemberActivities
                              andStaffArray:nil
                           andContactsArray:nil
                     inManagedObjectContext:self.managedObjectContext];
}

How can I transform this to work on the background, and then, when done saving, save the data and update the UI, without block the UI while is saving the 40.000 objects?

Thanks,

RL

Here's a good framework for you to try. Feel free to come back if you have any questions:

dispatch_queue_t request_queue = dispatch_queue_create("com.yourapp.DescriptionOfMethod", NULL);
dispatch_async(request_queue, ^{

    // Create a new managed object context
    // Set its persistent store coordinator
    AppDelegate *theDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
    [newMoc setPersistentStoreCoordinator:[theDelegate persistentStoreCoordinator]];

    // Register for context save changes notification
    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
    [notify addObserver:self 
               selector:@selector(mergeChanges:) 
                   name:NSManagedObjectContextDidSaveNotification 
                 object:newMoc];

    // Do the work
    // Your method here
    // Call save on context (this will send a save notification and call the method below)
    BOOL success = [newMoc save:&error];
    [newMoc release];
});
dispatch_release(request_queue);

And in response to the context save notification:

- (void)mergeChanges:(NSNotification*)notification 
{
    AppDelegate *theDelegate = [[UIApplication sharedApplication] delegate];
    [[theDelegate managedObjectContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
}

And don't forget to remove the observer from the notification center once you are done with the background thread context.

[[NSNotificationCenter defaultCenter] removeObserver:self];

How to log all methods used in iOS app

7 votes

I'm taking over the development of an iPad app for a client. There's a substantial amount of work that's already been done and I'm trying to piece together how the whole thing is designed to run.

One of the things I'd like to do is log which methods get called when the app runs. I've seen a custom DTrace script that's meant to log all methods from startup, but when I run it in Instruments I get no results.

What's the best way of logging the methods?

Inspired by tc's answer to a similar question here, I put together a debug breakpoint action that will log out the class and method name for every time objc_msgSend() is triggered in your application. This works similarly to the DTrace script I described in this answer.

To enable this breakpoint action, create a new symbolic breakpoint (in Xcode 4, go to the breakpoint navigator and create a new symbolic breakpoint using the plus at the bottom left of the window). Have the symbol be objc_msgSend, set it to automatically continue after evaluating actions, and set the action to be a debugger command using the following:

printf "[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)),*(long *)($esp+8)

Your breakpoint should look something like the following:

Breakpoint action

This should log out messages like this when run against your application:

[UIApplication sharedApplication]
[UIApplication _isClassic]
[NSCFString getCString:maxLength:encoding:]
[UIApplication class]
[SLSMoleculeAppDelegate isSubclassOfClass:]
[SLSMoleculeAppDelegate initialize]

If you're wondering where I pulled the memory addresses, read this Phrack article on the Objective-C runtime internals. Unfortunately, I think these memory addresses will only work against the Simulator, so you might need to tweak this to run against applications on the iOS devices.

Also, I think you'll see that logging out every method called in your application will overwhelm you with information. You might be able to use some conditions to filter this, but I don't know if this will help you to learn how your code executes.

Using iOS 5 features without breaking backward compatibility

6 votes

My application is currently compiled against the latest iOS 4.x SDK. Once iOS 5.0 SDK is out, would it be possible for me to use the new iOS 5.0 SDK features in my application and yet have it run on iOS 4 devices (but with the parts using the new features disabled)?

To answer the question generally, the Objective-C runtime is fully reflective, which means that you can query which methods an object supports (via respondsToSelector:) and get hold of classes by name at runtime (via NSClassFromString). iOS binaries also support the concept of weak linkage with frameworks, which means that the framework will be loaded if it is available but that you don't consider it a fatal error if the framework isn't available (as is the default behaviour).

That means that when Apple release new versions of the OS you can write code that uses new features on the latest version of the OS but functions fine without them if those new features are new bits of API.

Apple also sometimes supply new SDK features that aren't new APIs, such as when the Clang static analyser was added to Xcode. As those features usually don't require any runtime support they're fully usable. iOS 5 is a little unique because Apple's commits to the LLVM project suggest that there are some new compile time features in amongst the ARC stuff that rely on some runtime support. So they'll be unavailable, if indeed they're in the tools as Apple intend to distribute them.

NSString format

6 votes

I have a NSString I am getting from an array. There are multiple string objects in the array. I want to change the format of the string I get from array and display that new formatted string on UILabel. let me give one example :
String in array : 539000
String I want to display : 5.390.00

Now the problem is that the string I get from array may be 539000, 14200 or 9050. So the string I want to get are : 5.390.00, 142.00, 90.50
The correct format is :
Place a . before last two digits, again place a . before 3 digits from first .
I hope I have put my query in best possible way. Please help.

Thanks,
Nitish

USE this it will help

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
//[formatter setNumberStyle:NSNumberFormatterNoStyle];
//[formatter setPositiveFormat:@"###-###-####"]; 
[formatter setGroupingSeparator:@"."];
[formatter setGroupingSize:2];
[formatter setUsesGroupingSeparator:YES];
[formatter setSecondaryGroupingSize:3];

//[formatter setLenient:YES];
NSString *num = @"539000";
NSString *str = [formatter stringFromNumber:[NSNumber numberWithDouble:[num doubleValue]]];
[formatter release];
NSLog(@"%@",str);

How is [NSDate date] calculated?

6 votes

I'm using part of the current date in a scheme on a web server and I want to generate the same value on the device as on the server. In theory I thought about a case where these two values wouldn't be the same and the values on either end wouldn't match.

Which then led me to think - how, specifically, is [NSDate date] calculated when an app is running?

Edit: I guess what I'm really asking, is how does an iPhone get its time from an authoritative source? It appears it comes from a cell tower which I would assume are all synced somehow. Is this true?

Edit: Looks like it uses gettimeofday() which uses the system clock. And from Apple docs, looks like when you have the iPhone set to 'Set Automatically', it uses the correct time over the cell network.

Thanks,

you can find out by stepping through in the debugger or simply sample it for the callstacks.

it uses gettimeofday.

as such, you can't expect this value to be equal or perfectly synchronized on two devices.

Develop an iOS App for Cydia

6 votes

How can I start developing simple iOS tweaks for Cydia?

What's the difference in compiling an app for the official App Store and Cydia?

Developing a tweak is quite different from developing a self contained app. If you want to do it all yourself, read up on Objective C runtime programming. However, this is not how the vast majority of tweak developers do it, as there are several easier options.

If you have experience with Objective C (enough to be able to develop an app), there isn't a whole lot more you need to know to make a tweak. Dustin Howett, a developer who has made several tweaks for Cydia, made a tool called theos which vastly simplifies the process. You can read up on it here. There is also a very active IRC channel at irc.saurik.com #theos. Finally, you may want to check out the github pages of some popular tweak developers that use theos, so you can better understand the syntax (chpwn, DHowett, rpetrich).

Those three methods are how I learned to write tweaks, and once you understand theos it is really quite simple. theos also has systems for creating self contained apps as well as other plugins, so download it and see what is best for what you want. A quick google search will also turn up several useful theos tutorials (1, 2). Good luck!

One final thing to note is that you may want to hold off on developing for a couple weeks, the reason being that Apple may be releasing iOS 5 soon and things could change, as well as the fact that everyone on the #theos IRC will refuse to help with problems pertaining to iOS 5.

How to Start Three20 Photo Viewer in Thumbnail view?

6 votes

I followed How To Use the Three20 Photo Viewer by Ray Wenderlich tutorial it was very clear and working perfectly, my question as the title, How to Start Three20 Photo Viewer in Thumbnail view?

I am greatly appreciative of any guidance or help.

You should use TTThumbsViewController instead of TTPhotoViewController. There's a good example of it in three20 TTCategory sample app.

TTThumbsViewController also uses a photo source, so you won't have to change that much code. Your Photo viewer should extend TTThumbsViewController and implement the TTThumbsViewControllerDelegate delegate functions.

You can load the photo source in your viewDidLoad function:

///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)viewDidLoad {
  NSMutableArray* photos = [NSMutableArray array];
  for (int i=kImagesCount;i>=1;i--) {
    Photo* photo = [[[Photo alloc] initWithURL:[NSString stringWithFormat:@"bundle://%d.png", i]
                                      smallURL:[NSString stringWithFormat:@"bundle://%dt.png", i]
                                          size:CGSizeMake(400, 400)] autorelease];
    [photos addObject:photo];
  }

  self.photoSource = [[PhotoSource alloc]
                      initWithType:PhotoSourceNormal
                      title:@"Select Picture"
                      photos:photos 
                      photos2:nil];

}

What's fastest way to re-test iPhone core data migration to a new version?

5 votes

What's fastest way to re-test iPhone core data migration to a new version?

That is, how would one set up an easy/quick way to:

  • set up older version of app on simulator
  • run the new version of the app from Xcode which will as part of running it on the simulator effectively run the migration

BACKGROUND- haven't had to do a migration yet. It's not to me in Xcode how to do the first bullet in particular. Would one use a previous image/snapshot as part of the approach?

What I always did is:

  1. navigate to your applications folder /Users/username/Library/Application Support/iPhone Simulator/4.3.2/ notice the iOS version number, its the one you're using in the simulator
  2. there should be one or more folders with hash values, found the one you're working with
  3. in the documents folder should be your .sqlite database file (as long as you haven't changed the directory in code)
  4. backup that one (for example version 1)
  5. when you want to test the migration, simply replace this db file with your backup

(the hash may change when you delete and rebuild your app)

annotation on current location

5 votes

I'm working on the project in which i added a button on pressing it should take me to my current location on map and should show the blue indicator to indicate the location,here is the code:

-(IBAction)gotoLocation
{
if(curntloc)
 {
    MKCoordinateRegion mapRegion;   
    mapRegion.center = mapView.userLocation.coordinate;
    mapRegion.span.latitudeDelta = 0.0112872;
    mapRegion.span.longitudeDelta = 0.0112872;
    [self.mapView setRegion:mapRegion animated: YES];
 }
else
  { 
    curntloc = [[CLLocation alloc] initWithLatitude:21.192415 longitude:72.821159];
    MKCoordinateRegion mapRegion;
    mapRegion.center = mapView.userLocation.coordinate;
    mapRegion.span.latitudeDelta = 0.0112872;
    mapRegion.span.longitudeDelta = 0.0112872;
    [self.mapView setRegion:mapRegion animated: YES];
  }
}

This works fine on simulator you can see it in image,

on top is the button on pressing which i get the location statically passed on second loop but on iPhone it won't works

but when i try to test it on iPhone it's getting crashed.what may be the possible reasons can any one point out? thanks

First of all i want to tell you that from simulator you can't get current location. in your code you just used a static lat. long. and for the device i share a link just check.

http://pastebin.com/Vv1wvyBh

which may be helpful to you :)

Thanks.

object rotation is not proper - iPhone application

5 votes

I am facing a typical problem in rotating an object. Description is as given below
I have taken two CGPoint let say point1 and point2
point1 = (50,50)
point2 = (150, 50)
this point will draw a horizontal line.

Now i am drawing a rectangle with that point on it. Width is 100 and height is 10. Angle is 0.
see screen shot
enter image description here

works fine
now i change the point let say
point1 = (50,50)
point2 = (50,150)
this point will draw a vertical line.

For rectangle Angle is 90.
With this point rectangle is not drawing properly
see screen shot
enter image description here

My code for drawing rectangle is :

    CGPoint mid = CGPointMake((point1.x+point2.x)/2, (point1.y+point2.y)/2)
    CGPoint UL = CGPointMake(mid.x + ( Width / 2 ) * cos (A) - ( Height / 2 ) * sin (A) ,  mid.y + ( Height / 2 ) * cos (A)  + ( Width / 2 ) * sin (A));
    CGContextMoveToPoint(context, UL.x,routeView.frame.size.height - UL.y);
    CGPoint UR = CGPointMake(mid.x - ( Width / 2 ) * cos (A) - ( Height / 2 ) * sin (A) ,  mid.y + ( Height / 2 ) * cos (A)  - ( Width / 2 ) * sin (A));
    CGContextAddLineToPoint(context, UR.x,routeView.frame.size.height - UR.y);
    CGPoint BR = CGPointMake(mid.x - ( Width / 2 ) * cos (A) + ( Height / 2 ) * sin (A) ,  mid.y - ( Height / 2 ) * cos (A)  - ( Width / 2 ) * sin (A));
    CGContextAddLineToPoint(context, BR.x,routeView.frame.size.height - BR.y);
    CGPoint BL = CGPointMake(mid.x + ( Width / 2 ) * cos (A) + ( Height / 2 ) * sin (A) ,  mid.y - ( Height / 2 ) * cos (A)  + ( Width / 2 ) * sin (A));
    CGContextAddLineToPoint(context, BL.x,routeView.frame.size.height - BL.y);
    CGContextAddLineToPoint(context, UL.x,routeView.frame.size.height - UL.y);

    CGContextStrokePath(context);

Here A is Angle and it is not static, mid is middle point of point1 and point2

for more ref see this

Am I missing something? Please help me if you have any idea.......

Thanks,

Let me guess, it's actually rotated about 26 degrees too far, right?

(90 x 180) / Pi ~= 5156.62 = (360 x 14) + 90 + 26.62

You rotated it 90 radians by mistake.