我在 Swift Playground 中编写了以下代码,它会产生一个错误,提示“整数文字‘128’存储到‘Int8’时会溢出”。
我查看了Apple 的文档,其中没有提供数字的范围Int8
。进一步的研究表明,8 位整数可以存储 256 个值。
Swift 中某个类型的数字范围是多少Int8
?
var smallNumbers: [Int8] = [-127, 0, 3, 128]
我在可区分数据源初始化程序中的部分提供程序中有一个闭包,我checkCellView
从闭包内部设置变量。当我从错误的单元格switchCheckSelectionFunc()
中调用闭包时CheckCellView
,最终选择了错误的单元格。我该如何修复这个问题?
class QuestionnaireViewController: UIViewController {
var checkCellView: CheckCellView? {
didSet {
if checkCellView != nil {
print("type of closure,", type(of: checkCellView!.switchCheckSelection))
} else {
}
}
}
func configureDataSource() {
dataSource = CustomTableViewDiffableDataSource(tableView: tableView, cellProvider: { [self] tableView, indexPath, formItem in
// print("section,", indexPath.section)
self.checkCellView?.switchCheckSelection = { checkIsSelected in
if checkIsSelected {
checkCellView?.checkImageView.image = UIImage(named: "check-box-selected")!
} else {
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
}
}
switch formItem {
case .name(let name):
let cell = tableView.dequeueReusableCell(withIdentifier: PatientInfoCell.reuseID, for: indexPath) as! PatientInfoCell
cell.configure(title: "First Name")
return cell
case .lastName(let lastName):
let cell = tableView.dequeueReusableCell(withIdentifier: PatientInfoCell.reuseID) as! PatientInfoCell
cell.configure(title: "Last Name")
return cell
case .age(let age):
let cell = tableView.dequeueReusableCell(withIdentifier: PatientInfoCell.reuseID) as! PatientInfoCell
cell.configure(title: "Age")
return cell
case .gender(let gender):
let cell = tableView.dequeueReusableCell(withIdentifier: GenderCell.reuseID) as! GenderCell
cell.titleView.text = "Gender"
cell.femaleIcon.image = UIImage(named: "female-icon-deselected")!
cell.switchFemaleIconTapped = { isSelected in
if isSelected {
cell.femaleIcon.image = UIImage(named: "female-icon-selected")!
} else {
cell.femaleIcon.image = UIImage(named: "female-icon-deselected")!
}
}
cell.maleIcon.image = UIImage(named: "male-icon-deselected")!
cell.switchMaleIconTapped = {
if $0 {
cell.maleIcon.image = UIImage(named: "male-icon-selected")!
} else {
cell.maleIcon.image = UIImage(named: "male-icon-deselected")!
}
}
return cell
case .indwellingCardiacDeviceOrProsthesis(let bool):
checkCellView = tableView.dequeueReusableCell(withIdentifier: CheckCellView.reuseID, for: indexPath) as? CheckCellView
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
checkCellView?.switchCheckSelection = { checkIsSelected in
if checkIsSelected {
checkCellView?.checkImageView.image = UIImage(named: "check-box-selected")!
} else {
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
}
}
return checkCellView
case .predisposingHeartCondition(let bool):
checkCellView = tableView.dequeueReusableCell(withIdentifier: CheckCellView.reuseID, for: indexPath) as? CheckCellView
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
return checkCellView
case .intravenousDrugUse(let bool):
checkCellView = tableView.dequeueReusableCell(withIdentifier: CheckCellView.reuseID, for: indexPath) as? CheckCellView
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
return checkCellView
case .cardiacStructuralDisorder(let bool):
checkCellView = tableView.dequeueReusableCell(withIdentifier: CheckCellView.reuseID, for: indexPath) as? CheckCellView
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
return checkCellView
case .diabetic(let bool):
checkCellView = tableView.dequeueReusableCell(withIdentifier: CheckCellView.reuseID, for: indexPath) as? CheckCellView
checkCellView?.checkImageView.image = UIImage(named: "check-box-deselected")!
return checkCellView
}
})
}
}
class CheckCellView: UITableViewCell {
var titleView: UILabel = UILabel()
var checkImageView: UIImageView = UIImageView()
static var reuseID = "check-cell-reuseID"
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUp()
}
var switchCheckSelection: ((_ isSelected: Bool) -> Void)?
var checkIsSelected: Bool = false
func setUp() {
checkImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(switchCheckSelectionFunc)))
checkImageView.isUserInteractionEnabled = true
let stackView = UIStackView(arrangedSubviews: [
titleView,
checkImageView
])
stackView.axis = .horizontal
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor)
])
}
@objc func switchCheckSelectionFunc() {
checkIsSelected.toggle()
switchCheckSelection?(checkIsSelected)
}
func applySnapshot() {
guard case let .questionnaireData(formData) = data,
let formData = formData else {
return
}
var snapshot = NSDiffableDataSourceSnapshot<Section, FormItem>()
snapshot.appendSections(Section.allCases)
snapshot.appendItems(formData.patientInfoData, toSection: .patientInformation)
snapshot.appendItems(formData.checkAllThatApplyData, toSection: .checkAllThatApply)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
我正在尝试使用通用参数将通用数据注入视图控制器T
。我有一个协议Coordinator
,它声明一个关联类型 T 和一个data
类型 的变量T
。我的AppCoordinator
采用Coordinator
协议并将 的类型声明T
为String
。在我的AppCoordinator
课程中,我尝试使用通用参数 在视图控制器上设置数据T
。
我的想法是,当类实现 Navigable 协议时,它会采用一种具体的WelcomeViewController
类型,因此我应该能够设置 AppCoordinator 中的数据类型(在本例中为 String),并且也能够在视图控制器上设置该类型。不知何故,我认为为了使其工作,Coordinator 协议中的类型 T 必须与 Navigable 协议中的类型 T 匹配,但是当我尝试通过在 Coordinator 协议中进行设置来执行此操作时,我收到此错误:“无法从‘Navigable’访问关联类型‘T’;请改用具体类型或通用参数基”。AppData
data
associated type T: Navigable.T
我已经阅读了如何将依赖项注入 iOS 视图控制器?,以及以下章节:泛型解决的问题、泛型函数、类型参数、命名类型参数、类型约束、关联类型、泛型 Where 子句、具有泛型 Where 子句的关联类型、来自泛型。
我该如何解决这个问题?
protocol Coordinator<T> {
associatedtype T
var navigationController: UINavigationController { get }
var data: T? { get }
func start<T>(data: T?, viewController: any Navigable)
}
class AppCoordinator: Coordinator {
typealias T = String
var data: T?
init(data: T? = nil, navigationController: UINavigationController) {
self.data = data
self.navigationController = navigationController
}
var navigationController: UINavigationController
func start<T>(data: T?, viewController: any Navigable) {
var viewController = viewController
viewController.data = data
}
}
protocol Navigable<T> where T == AppData {
associatedtype T
var data: T? { get set }
}
enum AppData {
case coordinatorData
}
class WelcomeViewController: UIViewController, Navigable {
var data: AppData?
var appCoordinator: (any Coordinator)?
typealias T = AppData
override func viewDidLoad() {
setUp()
}
}
我有一个 API 类,在其中创建一个 URL 会话数据任务,当任务从 DispatchQueue.main.async 块内完成时,该任务会更新类中 birdResult 属性的值。
我的课程代码如下:
class BirdsAPI: ObservableObject {
static let url = URL(string: "https://api.inaturalist.org/v1/observations?iconic_taxa=Aves&per_page=50&order=desc&order_by=created_at")
@Published var birdResults: [BirdResult] = []
func fetchObservations() {
URLSession.shared.dataTask(with: URLRequest(url: BirdsAPI.url!)) { data, response, error in
guard error == nil else { return }
let decoder = JSONDecoder()
do {
let body = try decoder.decode(Body.self, from: data!)
DispatchQueue.main.async {
self.birdResults = body.results
}
} catch let error {
print("error decoding data, \(error)")
}
}.resume()
}
}
这是为什么?我该如何解决?