【问题标题】:Conditional NSString constants条件 NSString 常量
【发布时间】:2015-10-07 06:46:25
【问题描述】:

我将表格视图单元格 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];

}

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

【问题讨论】:

    标签: ios objective-c iphone ipad constants


    【解决方案1】:

    您不能使用 #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.xib 重命名为 FileCell~iphone.xib,其他 xib 也是如此。注意小写 p

    【讨论】:

    • 我浏览了文档,这看起来很有希望。让我试试看。
    • 谢谢罗伯!是的,它正在工作并且是最优雅的方式!
    【解决方案2】:

    导入

     @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
    

    【讨论】:

    • 由于您是在运行时定义这些变量,所以如果其他类正在使用这些变量,代码将无法编译,因为这些变量仍未定义。
    【解决方案3】:

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

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

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

    【讨论】:

    • 我的 iPhone 和 iPad 有不同的 XIB。尽管我担心的是,一个常量是否可以通过预处理器表达式等任何方式或任何其他更好的方法来表示两个不同的值。
    • 我不明白你的问题。
    【解决方案4】:

    可以通过以下几种方式完成:

    1. 在没有自动布局的情况下使用带支柱/弹簧的一个 xib 或使用自动布局启用所有屏幕尺寸。
    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
    

    【讨论】:

    • 这些不是常量,这通常会导致一些令人头疼的问题,因为值可以随时更改并且没有编译时错误。
    • 还有一件事,因为您是在运行时定义这些变量,所以如果其他类正在使用这些变量,代码将无法编译,因为这些变量仍未定义。
    • 要在整个应用程序中使用这些变量,我们可以将它们用作类级变量(静态),在任何其他类中使用类名获取这些变量,或者可以使用由 nsobject 扩展的管理器类来获取和设置这些变量的值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多