iPad/iPhone及Universal程序开发心得总结

来源:互联网 发布:张家口军事 知乎 编辑:程序博客网 时间:2024/05/22 01:35

 

转自:http://www.ieliwb.com/ipad-iphone-universal-dev/

1 因为iPad的universal只有一个binary,所以没有的函数和类要weak link,而且不能用条件编译(因为只能编译成3.2)。
判断是iPad还是iPhone:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
       
NSLog(@"iPad")
}
else 
{
      
NSLog(@"iPhone")
}

2 调试的时候,iPad模拟器只能认为是iPad,这时候,用3.2编译,然后选到3.0模拟器环境,别点build,直接点run。

 


3 popover创建的时候一定要这么写(即使放在if条件里)这个十分重要!否则iPhone调试会出错

 

SettingController *settingController = [[SettingController alloc]initWithNibName:nil bundle:nil];
    
    
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    
{        
        
UINavigationController *setting_navigationController =[[UINavigationController alloc]initWithRootViewController:settingController];
        
        
Class popoverClass = NSClassFromString(@"UIPopoverController");
        
if (popoverClass) {
            
UIPopoverController *popover = [[popoverClass alloc]initWithContentViewController:setting_navigationController];
            
popover.delegate = self;
            
[popover presentPopoverFromBarButtonItem:senderpermittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
        
}
        
[setting_navigationController release];
    
}
    
else
    
{
        
[self.navigationController pushViewController:settingControlleranimated:YES];
    
}
    
    
[settingController release];

4 相关设置:
Base SDK = iphone device 3.2
Target Devise Family = iPhone/iPad
iPhone OS Deployment Target = iphone device 3.1.3
程序Target的iPhone OS Deployment Target的build setting必须设置为3.13或者更早(这样会带来程序的兼容性问题,比如不能用3.2SDK里面的API,也不能使用在3.2SDK里面被Deprecated的API)

 


5 3.2的时候可以接iPhone真机以Universal的形式调试。

 


6 将一个现有的iPhone程序升级到支持iPad的方法:
1)选择Prject–>The Upgrade Current Target for iPad
2)这里会有两个选项,升级为Universal或者创建一个单独的iPad target

 


7 iPad 至少支持一个方向的180度旋转。推荐支持4个方向。并提供横向与纵向的启动画面。
1)default图片根据ipad的方向来变换方向设置:
Filename Dimensions
Default-Portrait.png * 768w x 1004h
Default-PortraitUpsideDown.png 768w x 1004h
Default-Landscape.png ** 1024w x 748h
Default-LandscapeLeft.png 1024w x 748h
Default-LandscapeRight.png 1024w x 748h
Default.png Not recommended

 

2)旋转方向时reload view,重置控件大小:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{    
    
UIImageView *logoView = (UIImageView *)[self.viewviewWithTag:LOGO_VIEW_TAG];
    
logoView.frame = CGRectMake((self.view.frame.size.width-320)/250320,120);
    
    
UITextView *textView = (UITextView *)[self.viewviewWithTag:TEXT_VIEW_TAG];
    
textView.frame = CGRectMake(30.0f,200.0f,self.view.frame.size.width -60.0f,380.0f);
}

再一次见证了不用IB的方便,还有控件的大小尽量不要用具体的数字,用self.view.frame.size.width,….代替.如:
table = [[UITableView alloc] initWithFrame:CGRectMake(0.0f,0.0f,self.view.frame.size.width,self.view.frame.size.height) style: UITableViewStyleGrouped];


8 关于ICON图标,准备3张图:72×72(MyLargeIcon.png),57×57(Icon.png),48×48(MySmallIcon.png)

 

 

 

------------------------------------------------------------------------------------------------------------------------

 

原文地址:http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html

 

Well, the NDA has finally lifted, so we can start talking about iPhone SDK 3.2 and the iPad. The logical starting place seemed to be how to convert your existing applications into a “Universal App” that runs natively both on the iPad and the iPhone/iPod touch. Now, a lot of you have likely already had to figure this stuff out so you could get your updated app on the store today, but for those who didn’t go the early adopter route, let’s take a few minutes to look at the process. It’s pretty straightforward but there are a few gotchas.

Note: There are some additional things you should know, so read this post alsobefore tackling your update.

 

 

Targeting All Devices

The first thing you have to do is identify that you want to build your existing application as a universal application. For this article, I’m using the Xcode project from OpenGL ES Particle Generator Application, but I’ll try to keep the information general. Note: the following step is not needed if you use Xcode’s Update Project Target for iPad option talked about here.

Bring up your Project Info window in Xcode by either double-clicking on your project’s root node in the Groups & Files pane or selecting Edit Project Settings from the Project menu and then navigate to the Build tab. Now, the change we’re about to make needs to be made to all configurations, so make sure that the Configuration popup menu is set to All Configurations, otherwise you’ll only make the change on one configuration.

We need to change a setting called Target Device Family, so type Target into the search bar, or just search for that entry manually (it’ll be under the Deployment heading). Right now, it should look like this:

See how it says iPhone? Yeah, you know what to do. Click on it and change it so it readsiPhone/iPad, like so:

Good! now you’re done, right? Most likely, no.

 

Auditing for Hardcoded Sizes


The next thing you’re going to want to do is audit your application to see if you hard-coded the screen size anywhere in your application. You shouldn’t have hardcoded those values, but let’s face it, we’ve all done it. A Project Find (⌘⇧F) for 320 and 480 and that should turn up any of those hardcoded values. In the Particle Generator code, I did it in only one place, in code that creates a UIImage of the OpenGL view. The line of code where I did it looks like this:
    CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

Usually, the fix for this will be obvious. Instead of hardcoding, you want to pull the width and height from the OpenGL view. The code where I did it actually exists on the GLView class, so I can fix it like so:

    CGImageRef imageRef = CGImageCreate(self.frame.size.width, self.frame.size.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

But, what if what you’ve hardcoded is the actual size of the view? Then you need to pull the size from the main screen instead of the view. That’s easy enough to do.

    UIScreen *screen = [UIScreen mainScreen];    [myView setFrame:[screen applicationFrame]];

 

Dealing with Different Window Sizes


Most likely your application’s one instance of UIWindow is contained in your MainWindow.xibfile that gets loaded automatically. Most likely, that Window is hardcoded to 320×480. Now, you might think that you can just go into Interface Builder and set the autosize attributes for the window and it will get resized for you at launch. You would be wrong. There is no automatic check to make sure your window is the right size.

 

You have to make sure that the window is the right size for the device you’re running on. There are, basically, two ways of doing that. If your application is such that you just need to resize the window and your autosize attributes will take care of making everything look nice, then you can just handle this programmatically in applicationDidFinishLaunching: by setting the window’s size to the size of the screen, less the status bar andy any other objects controlled by the iPhone OS (this is known as the Application Frame). Doing this looks almost exactly like setting the size of the view above:

    CGRect  rect = [[UIScreen mainScreen] bounds];    [window setFrame:rect];

Now, this is actually a good approach for the Particles application because it has one full-screen view. However, the iPad and the iPhone are really different devices, and there are several UI components available on the iPad that aren’t available (at least yet) on the iPhone, such as split views and pop up views. For many applications, especially complex applications using a lot of UIKit views and controls, you’re probably going to want to provide completely different NIB file based on which device on which the code is running.

 

Info.Plist Device-Specific Entries


The one really important nib file in every iPhone application is, of course, MainWindow.xib, and there has to be a way to tell your application to use a different MainWindow.xib for different devices. In fact, there is. For each key that Info.plist supports, such NSMainNibFile, which is used to specify the name of the application’s main nib file, you can now specify device-specific entries. If you provide a device-specific entry for the device the application is currently running on, it will use the device-specific value, otherwise it will just use the normal value.

 

Device-specific keys are exactly the same as the original or default key except the key name is followed by a tilde (~) and then the name of the device in all-lowercase letters. So, to tell our application to load a different nib file for the iPad, we can add a key calledNSMainNibFile~ipad and then specify the name of the nib file to use when launching on an iPad. For the iPhone and iPod touch, it will continue to use the default value, MainWindow.xib, but for the iPad, it will use the nib file you’ve specified in the new, device-specific key.

You can add a new version of MainWindow.xib to your project by selecting the Resourcesgroup and choosing Add New File from the File menu. From the New File Assistant, selectUser Interface from under the iPhone OS, then select Application XIB, and make sure you select the right device in the Product drop-down.

Make sure you remember to connect all the outlets and actions in this new nib to the same outlets and actions you used in the other nib. Remember, only one of the application nibs will be loaded, so there’s no conflict.

For any key in the Info.plist file, you can use this same technique to override the default value with a device specific. You could, for example, have the iPhone version start in Portrait and the iPad version start in landscape, like so:

    ...    <key>UIInterfaceOrientation</key>    <string>UIInterfaceOrientationPortrait</string>    <key>UIInterfaceOrientation~ipad</key>    <string>UIInterfaceOrientationLandscapeLeft</string>    ...

 

Programmatically Determining Device


If you have code that needs to vary depending on whether it’s running on the iPad or iPhone/iPod touch, Apple has provided a new macro called UI_USER_INTERFACE_IDIOM() that will tell you that. There are currently two values defined, UIUserInterfaceIdiomPhone andUIUserInterfaceIdiomPad, and this macro will return the value that corresponds to the device being run. So, for example, if you needed to push a view controller onto the navigation stack, but wanted a different nib used for the iPad than the iPhone, you might do this:
    MyController *controller = nil;    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)        controller = [[MyController alloc] initWithNibName:@"MyiPadNib" bundle:nil];    else        controller = [[MyController alloc] initWithNibName:@"MyiPodNib" bundle:nil];    [self.navigationController pushViewController:controller animated:YES];    [controller release];

If you need finer-grain control, and need to know exactly which device, there’s no official, supported way to determine the exact device. The vast majority of the time you you think you need to know the device, you don’t actually need to know the device, you just need to know which features are supported. Even though you can find code around the web that will determine the device based on UIDevice, you really shouldn’t base your logic on that because such code can be fragile since you don’t know what future devices will exist, or what features they will have.

In cases like the Image Picker, Apple provides a way to determine which features are available on your device, such as whether there’s a camera, and whether that camera supports video. When Apple hasn’t provide a specific check or test, what you can do is useNSClassFromString(), which (as is probably obvious from the name) creates a Class instance based on the name of a class contained in a string. If this returns nil, then you know the class you’re asking about isn’t available. You can wrap your code that uses classes that aren’t available everywhere in these checks and make code that works correctly on all devices, and will continue to do so in the future (for the most part – it’s never possible to 100% future-proof code). Here’s an example of checking for the existence of the UISplitViewController, which is a new class only available on the iPad:

    Class splitViewController = NSClassFromString(@"UISplitViewController");    if (splitViewController)    {       UISplitViewController* mySplitViewController = [[splitVCClass alloc] init];       // ... configure, use, then release    }

You can do something similar with C functions by checking if the function is NULL For example, one of the frameworks added with iPhone SDK 3.2 is CoreText.framework. If we wanted to use the function CTFontCreateWithName() to create a new font using that framework, we could wrap the logic in an interface idiom check, like above, or we could just check to see if the function we want to use exists by seeing if the symbolCTFontCreateWithName is NULL at runtime, like so:

    if (CTFontCreateWithName != NULL)        CTFontFontRef myFont = CTFontCreateWithName(@"Comic Sans", 14.0, NULL);

 

原创粉丝点击