条件 NSString 常量

Conditional NSString constants

我声明 table 查看单元格 XIB 名称为 NSString 常量。 iPad 和 iPhone 有单独的 XIB,我想引用两个版本的 XIB,使用相同的常量名称但值不同。

BaseViewController.h

#import <UIKit/UIKit.h>

extern NSString * const FileCell;
extern NSString * const FolderCell;

BaseViewController.m

#import "BaseViewController.h"

//I am sure that this cannot be done 
//since I cannot check device type at preprocessing time/compile time

#if IS_IPAD_DEVICE// device check, not viable
NSString * const FileCell = @"FileCell";
NSString * const FolderCell = @"FolderCell";
#else
NSString * const FileCell = @"FileCell~iPhone";
NSString * const FolderCell = @"FolderCell~iPhone";
#endif

//I don't want to declare separate constants with different names for iPhone table view cells. 
//I want to use same name of constants but the string values are different for iPad and iPhone. 

@implementation BaseViewController

-(void)viewDidLoad
{
    [super viewDidLoad];
    [self.collectionView registerNib:[UINib nibWithNibName:FileCell bundle:nil] forCellWithReuseIdentifier:FileCell];
    [self.collectionView registerNib:[UINib nibWithNibName:FolderCell bundle:nil] forCellWithReuseIdentifier:FolderCell];

}

许多其他文件和子控制器也使用这些常量。 知道我怎样才能完成这件事。我不想使用属性并覆盖它们的吸气剂。一些优雅的解决方案?

可以通过多种方式完成,例如:

  1. 使用一个带有 struts/springs 的 xibs 而不使用自动布局或使用自动布局为所有屏幕尺寸启用。
  2. 其他方式,您必须使用属性或全局变量在屏幕开始时设置 NSString 的值。

ViewController.h

@interface ViewController : UIViewController

NSString * FileCell;
NSString * FolderCell;

@end  

ViewController.m

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
    {
        FileCell = @"FileCell";
        FolderCell = @"FolderCell";

    }else{
        FileCell = @"FileCell~iPhone";
        FolderCell = @"FolderCell~iPhone";
    }
    // Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

进口

 @interface ViewController : UIViewController

 extern NSString * FileCell; extern NSString * FolderCell;

 @end

进口"ViewController.h"

 @interface ViewController ()

 @end

 @implementation ViewController

 (void)viewDidLoad {
   [super viewDidLoad];

   if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) { 
          FileCell = @"FileCell";  
          FolderCell = @"FolderCell";


   }
  else
    { 
     FileCell = @"FileCell~iPhone"; FolderCell = @"FolderCell~iPhone"; 
     } 

      [self.collectionView registerNib:[UINib nibWithNibName:FileCell bundle:nil] forCellWithReuseIdentifier:FileCell];

       [self.collectionView registerNib:[UINib nibWithNibName:FolderCell bundle:nil] forCellWithReuseIdentifier:FolderCell];
   }


   (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }

  @end

在程序化方法中没有空间。最后,您需要单元格的名称及其标识符。

在 iOS 8 之前的故事板方法中,我们为 iPad 和 iPhone 提供了单独的故事板。他们每个人都有自己的布局,因此也有自己的牢房。我认为这是一个更干净的解决方案。尽管我们尝试在通用情节提要上做很多事情,但 iPad 仍然有更多的空间来展示东西。因此,如您在 Android 平板电脑应用程序中看到的那样拉伸内容毫无意义。

我的建议是,拆分 iPad 和 iPhone 故事板。他们仍然可以共享相同的 类。毕竟我们早在 iOS 9 之前就在我们的应用程序中使用了 splitview。

您不能使用 #ifdef 执行此操作,因为可以在 iPhone 和 iPad 上使用相同的可执行文件。

但是你不需要 #ifdef,因为 iOS 自动为 iPhone 和 iPad 加载不同的资源文件(包括 XIB 文件),如果你正确命名您的资源。 Resource Programming Guide.

中记录了此行为

具体来说,在 iPhone 上,当您请求 FileCell.xib 时,如果该资源存在,它将自动加载 FileCell~iphone.xib。在 iPad 上,如果该资源存在,它将自动加载 FileCell~ipad.xib

请注意,iOS 使用 区分大小写的 文件系统,这与 Mac OS X 不同。所以您需要做的就是重命名FileCell~iPhone.xibFileCell~iphone.xib,对于你的其他 xibs 也是如此。注意小写 p.