如何在将成为全局的 if/switch 语句中声明一个变量?

Posted

技术标签:

【中文标题】如何在将成为全局的 if/switch 语句中声明一个变量?【英文标题】:How to declare a variable within if/switch statements that would become global? 【发布时间】:2017-09-12 23:29:49 【问题描述】:

我正在尝试使用多个自定义 UITableViewCells,而不必为每个选项复制 cellForRowAt 方法中的所有代码

我正在创建一个用于学习目的的实时聊天应用程序,它根据消息发送者是否是用户的天气来区分单元类。我知道如何使用 if-else 或 switch 语句为 cellForRowAt 提供相关的 ReusableCell,但问题是:

    处理单元格属性的 200 行代码 可以访问单元格变量,除非我在这些之外定义它 切换/如果语句。 当我在函数头中定义它时,它需要一个预定义类型 如果我选择任何一种类型作为默认类型并声明它,我会收到它们不兼容的错误,而实际上从代码的角度来看它们是 100% 相同的(只是设计不同) . 如果我将其声明为通用 UITableViewCell 类型,则该类型缺少我的所有自定义属性。 如果我尝试创建一个公共基类,我将无法链接我的 @IBOutlets 和@IBActions,它们是大部分的共同点。 如果我尝试构建一个协议,该协议不支持任何东西 @IB。

如果我可以在 if/switch 语句中声明单元变量并使其对我的其余代码可见,而不必将其嵌套在 if/switch 中,则可以解决此问题。有什么办法吗?

PS。我知道我可以通过为自定义 tableview 单元格的每个变体复制 200 行代码来克服这个问题,但我的直觉告诉我必须有更聪明的方法来做到这一点。

这里有一个代码 sn-p 来说明问题:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 


    // Get the info about the message from an array
    let message = messageArray[indexPath.row]

    // Pick cell style based on who the sender is
    var isUsersPost = 0
    if message.sender == userID 
        isUsersPost = 1
    

    switch isUsersPost 
    case 1:
        let cell = chatTableView.dequeueReusableCell(withIdentifier: "rightChatCell") as! RightChatViewCell
    case 0:
        let cell = chatTableView.dequeueReusableCell(withIdentifier: "chatCell") as! ChatViewCell
    default:
        let cell = chatTableView.dequeueReusableCell(withIdentifier: "chatCell") as! ChatViewCell
    

    // fill in the cell properties with data - ca 200 lines of logic that is already optimised as much as reasonable
    cell.messageTextLabel = message.text 
    ... etc

    return cell   
    

这是我的 TableViewCell 类(它们是相同的):

 import UIKit

 class RightChatViewCell: UITableViewCell 

var likeTask : (() -> Void)? = nil
var commentTask : (() -> Void)? = nil
var photoTask : (() -> Void)? = nil


@IBOutlet weak var messageBoxView: UIView!
@IBOutlet weak var messageTextLabel: UILabel!
@IBOutlet weak var nicknameLabel: UILabel!
@IBOutlet weak var profilePhotoView: UIImageView!
@IBOutlet weak var messageDateLabel: UILabel!
@IBOutlet weak var messageCommentLabel: UILabel!

@IBOutlet weak var likeButton: UIButton!
@IBOutlet weak var messageLikesLabel: UILabel!
@IBOutlet weak var messagePhotoView: UIImageView!

override func awakeFromNib() 
    super.awakeFromNib()
    messagePhotoView.isHidden = true
    self.selectionStyle = UITableViewCellSelectionStyle.none
    // Add photo Tap gesture recognizer
    messagePhotoView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(photoTapped)))


override func setSelected(_ selected: Bool, animated: Bool) 
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state


@objc func photoTapped() 
    print("Photo tapped")
    if let btnAction = self.photoTask
    
        btnAction()
    


@IBAction func likeTapped(_ sender: Any) 
    print("Like tapped")
    if let btnAction = self.likeTask
    
        btnAction()
    


@IBAction func commentTapped(_ sender: Any) 
    print("Comment tapped")
    if let btnAction = self.commentTask
    
        btnAction()
    



【问题讨论】:

只有当你的两个单元类有一个共同的基类并且你要在swift之后设置的所有属性或者你的两个单元类都符合声明这些公共属性的协议。 哇!谢谢你。这是个好主意,我现在就试试。在这种情况下,协议会比类更有意义吗?如果我采用协议路由,我将如何声明单元变量? 视情况而定。如果唯一的共同点是某些属性,那么协议可能是更好的选择。如果这两个类共享共同的功能,那么基类可能是避免在两个类中复制代码的更好选择。 好的,假设我正在使用基类。如何处理当前为每个子类引用不同 .xib 文件的 @IBOutlets 等?所以我不能将它们连接到基类变量,但必须分别为每个子类做,对吧? 99% 的变量和功能与 IB 相关。 尝试了这两个选项,但问题在于 IBoutlets 不起作用:( 【参考方案1】:

如果将类级别的变量声明为null、0或'';然后在您的 try 和 catch 中实例化它们,尽管您可能需要在类中包含一个异常处理程序,因为如果实例化不成功,您将需要处理该问题。

查看有关范围和变量的链接 https://www.cs.umd.edu/~clin/MoreJava/Objects/local.html

【讨论】:

试过了,声明时出错——“nil”需要上下文类型” :) 返回第 1 格 :(

以上是关于如何在将成为全局的 if/switch 语句中声明一个变量?的主要内容,如果未能解决你的问题,请参考以下文章

选择结构ifswitch

if,switch语句

11.条件语句if,switch

02_5if switch分支与循环语句

laravel 视图流程控制,if switch for loop

控制语句 for while if switch