【问题标题】:Convert C# generic method to objective-C将 C# 泛型方法转换为 Objective-C
【发布时间】:2013-05-17 20:36:19
【问题描述】:

长篇大论:

我的一位同事向我寻求帮助。我是一名 C# 开发人员,他是一名 iOS 开发人员,阅读彼此的代码有时会给我们一些很好的见解。

他正在编写一些函数,该函数需要返回一个基本类型为UITableViewCell 的对象,并以整数作为输入。实际返回类型是UITableViewCell 的子类。他问我是否知道比这样简单的开关更好的解决方案:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (row) {
        case 0: {
            NSString *CellIdentifier = @"personCell";

            PersonInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (cell == nil) {
                cell = [[PersonInfoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            }
            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            return cell;
            break;
        }
        case 1: {
            NSString *CellIdentifier = @"photoCell";

            PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (cell == nil) {
                cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            }
            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            return cell;
            break;
        }
        default:
            return nil; //Don't care about this atm. Not the problem.
            break;
    }
}

我的 C# 实现如下:

public UITableViewCell TableViewCellForRowAtIndexPath(UITableView tableView, NSIndexPath indexPath)
{
    switch(indexPath.row)
    {
        case 0:
        return MakeCell<PersonInfoCell>();
        case 1:
            return MakeCell<PhotoCell>();
        default:
            return null; //Still doesn't matter
    }
}


public TCell MakeCell<TCell>() where TCell : UITableViewCell, new()
{
    TCell cell = new TCell();
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

public class PersonInfoCell : UITableViewCell
{
    //Dont care about implementation yet....
    //TL;DR
}

public class PhotoCell : UITableViewCell
{
    //Dont care about implementation yet....
    //TL;DR
}

短篇小说:

有谁知道将我的 C# 通用代码转换为 Objective-c 等效项的方法?


更新 1

我们基于 Nicholas Carey 的想法的错误实现。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (row) { case 0: { NSString *CellIdentifier = @"personCell"; PersonInfoCell *cell = (PersonInfoCell *)[self makeCell:CellIdentifier]; //Do PersonInfoCell specific stuff with cell return cell; break; } case 1: { NSString *CellIdentifier = @"photoCell"; PhotoCell *cell = (PhotoCell *)[self makeCell:CellIdentifier]; //Do PhotoCell specific stuff with cell return cell; break; } default: return nil; //Don't care about this atm. Not the problem. break; } } - (id *)makeCell:(NSString *)cellIdentifier { id cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; // <---- how does this method know it is a PhotoCell I want? //PhotoCell??? } cell.selectionStyle = UITableViewCellSelectionStyleNone; return cell; }

【问题讨论】:

    标签: c# objective-c uitableview generics


    【解决方案1】:

    在 Objective-C 中,类是第一类构造,可以像任何其他对象一样传递和使用。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *cellIdentifier = nil;
        Class cellClass = nil;
        switch (row) {
            case 0:
                cellIdentifier = @"personCell";
                cellClass = [PersonInfoCell class];
                break;
            case 1:
                cellIdentifier = @"photoCell";
                cellClass = [PhotoCell class];
                break;
            default:
                return nil; //Don't care about this atm. Not the problem.
        }
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil)
            cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        return cell;
    }
    

    如果你真的想要分解出工厂方法,你可以这样做:

    - (UITableViewCell *)getOrCreateCellForTable:(UITableView *)tableView withIdentifier:(NSString *)cellIdentifier class:(Class)cellClass
    {
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
      if (cell == nil)
          cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
      cell.selectionStyle = UITableViewCellSelectionStyleNone;
      return cell;
    }
    

    如果您想摆脱成对的 cellIdentifiercellClass 参数,一种选择是在您使用的每个单元类上创建一个 defaultIdentifier 类方法(static 方法,用 C# 说法) .这样,您可以只将类传递给工厂方法,工厂方法可以查询类以获取正确的标识符。

    【讨论】:

    • 大卫米切尔。谢谢!我们对其进行了一些编辑,并且效果很好。请参阅@Apox 他对完整实施的回答。
    【解决方案2】:

    基于 David Mitchell 的代码,我们(Synercoder 的同事)想出了这个,完美运行!

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *cellIdentifier = nil;
        Class cellClass = nil;
        switch (indexPath.row) {
            case 0: {
                cellIdentifier = @"personCell";
                cellClass = [PersonInfoCell class];
                PersonInfoCell *personInfoCell = (PersonInfoCell *)[self getOrCreateCellForTable:tableView withIdentifier:cellIdentifier class:cellClass];
                personInfoCell.delegate = self;
                return personInfoCell;
            }
            case 1: {
                cellIdentifier = @"photoCell";
                cellClass = [LastMeasureMent class];
                LastMeasureMent *measurementCell = (LastMeasureMent *)[self getOrCreateCellForTable:tableView withIdentifier:cellIdentifier class:cellClass];
                measurementCell.selectionStyle = UITableViewCellSelectionStyleBlue;
                return measurementCell;
            }
            default: {
                cellIdentifier = @"photoCell";
                cellClass = [LastMeasureMent class];
                LastMeasureMent *measurementCell = (LastMeasureMent *)[self getOrCreateCellForTable:tableView withIdentifier:cellIdentifier class:cellClass];
                measurementCell.selectionStyle = UITableViewCellSelectionStyleBlue;
                return measurementCell;
            }
        }
    
    
    }
    
    - (UITableViewCell *)getOrCreateCellForTable:(UITableView *)tableView withIdentifier:(NSString *)cellIdentifier class:(Class)cellClass
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil)
            cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        return cell;
    }
    

    谢谢大卫!

    【讨论】:

      【解决方案3】:

      看到这个问题:Are there strongly-typed collections in Objective-C?

      Objective-C 是后期绑定和动态类型的,因此您不需要泛型。您可以向对象发送任何消息。它用它做什么取决于对象。具有静态类型的早期绑定语言,如 C#、Java、C++ 需要泛型。没有它们,问题就不会[轻易地]知道它可以或不能对包含的对象做什么。

      【讨论】:

      • 如果我在 Objective-c 中创建了一个MakeCell 方法并且返回类型是id。然后在开关中将其转换为正确的类型。可能...但是MakeCell 方法如何知道在该方法中要实例化什么?如何将方法传递给 MakeCell 方法,以便它知道创建 PersonInfoCellPhotoCell
      • 我们添加了我们认为您的意思。您能否详细说明我们的实施中缺少什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      • 1970-01-01
      相关资源
      最近更新 更多