Automating xcode update - iphone

I have 1 app built in xcode for iPhone and iPad which is altered slightly differently for different companies but it is the same base app exactly except for the name, certain colour settings, website link and databased referenced too along with customers custom graphics.
When we have to do an update to the build I have to update the same app around 200 times now only changing an if statement to point towards a certain companies version, the identifier, name and graphics and it's extremely repetitive and I'm wondering if there would be anyway to go about building a script to automate this.

The Xcode command-line tools installs a utility called xcodebuild that you use in scripts. Facebook's xctool is worth taking a look at too.

You probably should make a config file with compiler directives in it. Define constants in the target and then write out something like this:
#ifdef TARGET1
#define PRIMARY_BACKGROUND [UIColor whiteColor]
#define WEB_SERVICE #"http://www.targert1.com/services"
#endif
#ifdef TARGET2
#define PRIMARY_BACKGROUND [UIColor blackColor]
#define WEB_SERVICE #"http://www.targert2.com/services"
#endif

Related

How can I enable a #define automatically in XCode when the simulator is selected?

I have a few files that I want compiled differently when I'm testing my iPhone app on the simulator, so I'm using a #define simulator macro in those files. I'm trying to figure out how I can comment out this #define statement and tell XCode to define this macro when the simulator is selected. How can I do this?
I read a couple other similar questions on here and tried adding a conditional assignment in the "Other C Flags" build settings for the "Any iOS Simulator SDK" architecture with the value set to "-simulator=1", but that doesn't seem to do anything.
Thanks in advance for your wisdom!
#if TARGET_IPHONE_SIMULATOR should do the trick.
You don't need your own #define for this: Apple provides one for you. Just use
#if TARGET_IPHONE_SIMULATOR
around the code you want specific to the simulator. (You'll need to include the TargetConditionals.h header for this, but it's probably already included if you import the frameworks.)

IPhone simulator vs. Device issue (open GL)

I am developing an iPhone application using openGl ES 2.0, and after a lot of testing in the simulator I installed the application on my iPhone(3GS) to see how well it preformed. When the app launched it started up fine with no errors, but nothing showed up, however the background was the appropriate color.
Does anybody have any ideas/pointers about what might be causing this issue? If code/details would help just let me know what section of code you would like to see.
Check the constraints on various functions you may use. For example, by default the width and height for glTexImage2D must each be powers of 2 (or powers of 2 plus 2, if you are using a border). There is an extension that allows for non-power-of-two textures, but in my experience this extension is not present or is not completely implemented on at least some devices (i.e. it works for GL_CLAMP_TO_EDGE but not GL_REPEAT).
The Device is strict about case-sensitivity in filenames -- check to make sure that if you are loading Shaders, that the filenames referenced in your code are identical to their actual filesystem names.
Also, if you are in xCode 4, go to your Target Build Phases settings and make sure all of the shaders you use are in Copy Bundle Resources.
Finally, if the shaders appear in 'Compile Sources', you should remove them from there. You'll need to Clean your project and then re-build.

Interface Builder: Choose media based on target

In Xcode I use targets to release several apps versions which share some base code and tend to have different graphics.
i.e. Pretending I have target JOHN and target DOE. I could add different images named exactly example.png to the bundle, and have each one targeted respectively. The code does not need any changes this way.
UIImageView *image = [UIImageView alloc] initWithImage:[UIImage imageNamed:#"example.png"]];
If instead I named each image per different version I would end up with something similar to this:
NSString *imageName;
#ifdef JOHN
imageName = #"johnExample.png";
#else
imageName = #"doeExample.png";
#endif
UIImageView *image = [UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
Having several versions and many images this quickly becomes messy and having a huge file with constants looks to me like an overkill, so I end up with the first option.
The problem is:
While working on nibs files, Interface Builder just appears to load example.png randomly. So if I'm working on target JOHN it's an annoyance that IB just decided to load example.png from the DOE target.
There's any way for Interface Builder to load media based on a target?
Just to close this question, the answer is: no.
As of Jan '11, you can't load media based on a target on Interface Builder, but you could use some workarounds, as Digital Robot and my own description in the question pointed out.
why not have this define at the beginning of the code
#ifdef JOHN
#define APP #"john"
#elseif DOE
#define APP #"doe"
#endif
and then, every time you want to use this, you may have...
imagename = [NSString stringWithFormat:#"%#Example.png", APP];
That should work. This may be new because some time has passed and I just learned that recently. Don't know wether this was possible ages ago when you acutally asked this question :) But it may be useful for others searching for a solution.
When adding a target to a project within xcode then it creates a subfolder in the file system. There is one subfolder for each of the taragts. The basic idea is, as far as I understand it, that all commonly used files are on the upper level in the project main directory and those that are individual to each target are in their respective directory.
(A bit like localized versions of files.)
So you may put the image of John as example.png in /project/john and the image of Doe as example.png in /project/doe.
You should double check that the correct versions of each image are included in the build settings for each of the targets respectively. (Copy Boundle Resources)
Doing so "example.png" is included only once in the boundle. Randomly loading of one image or the other should not longer happen, although you refer to it as "example.jpg" within your code.

How to make iAds work on a 3.0 + iPhone-iPad app?

I created a universal app for the iPhone-iPad. I'm only working on the iPhone part at the moment. In the header file for the view controller for the iPhone one, I import the adbanner header and create an adbannerview variable with a matching property. I don't make it in the nib file but rather check at run time if the class exists, if it does, I create an adbanner programmily and then attach the adbannerview variable to it so I can refer to it inside other functions. Everything works on the 4.0 simulator. I also weak linked the iad class.
So if I take the same code to an earlier version of xcode and try to run using the 3.0 sim, it gives all these errors saying I can't import the header and make the adbannerview variable and the property, how do I get around this?
Thanks. If you need more details or my code, just ask.
The AdLib Framework and iAds are only available in iOS > 4.0. For example, see the docs for ADBannerView:
Availability Available in iOS 4.0 and
later.
If you are trying to build the app on an older version of the sdk (not just run the binary on a older device) and are getting errors when you try to import the headers like your question suggests, you could try wrapping the imports that fail in a #ifdef directive that tests for the availability macros from Availability.h, something like:
#ifdef __IPHONE_4_0
// iOS 4 specific imports here
#endif

Make iPad app a Universal app

I have an iPad app that I would like to make Universal, however this seems alarmingly difficult. I've changed things around so that I support both builds, but when building, I get lots of errors about using UIPopOvers. Here're my questions:
Why does UI_USER_INTERFACE_IDIOM() not compile or register on 3.1.3?
Can I conditionally have variables in a class definition based on UI_USER_INTERFACE_IDIOM()?
If not, should I make two different view controllers?
Thanks!
Why does UI_USER_INTERFACE_IDIOM() not
compile or register on 3.1.3?
The UI_USER_INTERFACE_IDIOM macro is only available starting with 3.2. Same restrictions for the userInterfaceIdiom property of UIDevice. This means that you can only get universal application starting with SDK 3.2.
Can I conditionally have variables in
a class definition based on
UI_USER_INTERFACE_IDIOM()?
No. The UI_USER_INTERFACE_IDIOM macro is only a runtime shortcut to get the current UI idiom of the device.
If not, should I make two different
view controllers?
If you have very different UI between the two devices, it is wiser to use two different view controllers, and to create the right one at runtime (in the application controller for example) by using the UI_USER_INTERFACE_IDIOM macro.
I had pretty good luck with just selecting the target then going to Project->Upgrade current target for iPad.
My app is pretty simple, consisting mostly of table views and webviews, but it's worth making a backup and trying...
And yes, you have to submit it as a 3.2 app that can target 3.1.*
There are also a lot of other stuff that you have to do:
Make sure that it can be viewed at any orientation (got rejected the first time for this).
Make sure that you have all the new images created. you have to have 3 or 4 icons, instead of just one like an iPhone app needed. (iPad icon, iPhone icon, small icon for spotlight, etc).
And of course iPad sized screenshots for the store.
A really nice way that I use to test if it's an iPad or iPhone is to check if the device can use a split view controller, since for the forseeable future no device with a screen as small as an iPhone will be able to use the split view controller. I just created a function to do this for me:
+(BOOL)isIpad{ return NSClassFromString(#"UISplitViewController") != nil; }
Then anywhere in my app that I want to display something different depending on device, I just do a check for it:
int width = 150;
if([NabAppDelegate isIpad]){
width = 350;
} else {
width = 150;
}
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5,10,width,25)];
This is a lot better than checking against OS version like I've seen some suggest.