Я создал вид прокрутки, в который встроено изображение, которое отображает изображения структуры, которую я создал. Над представлением прокрутки находится метка, которая отображает заголовок изображения. Структура (scrollViewDataStruct) содержит как заголовок, так и UIImage. Я назначаю эту структуру переменной в классе ViewController, которая называется scrollViewData.
scrollViewData - это массив scrollViewDataStruct. В настоящее время, для тестирования, он содержит пять предустановленных индексов (или значений ... как вы хотите их называть). В моем приложении также есть кнопка (за пределами прокрутки), которая при нажатии открывает камеру (или библиотеку фотографий) и позволяет пользователю загружать фотографии в приложение. Затем эта фотография помещается в переменную UIImage, а затем эта переменная добавляется к scrollViewData (пример в строках 100 и 101). Я хочу, чтобы мой scrollView обновлял imageViews, когда пользователь добавляет новую фотографию (так, когда вызывается didFinishPickingMedia). Это все работает отлично ... изображение правильно добавляется к scrollViewData. Проблема возникает, как только пользователь касается scrollView (после загрузки изображения). Приложение аварийно завершает работу и в строке 73 (которая находится в функции scrollViewDidScroll) выдает следующую ошибку: «Поток 1: Неустранимая ошибка: неожиданно обнаружен ноль при развертывании необязательного значения.»
Я понимаю, что функция viewDidLoad вызывается только один раз (при первом запуске этого контроллера просмотра). Я попытался взять весь код (кроме назначения делегата [строка 32] и присвоения значений scrollViewData [строки 34-38]) из viewDidLoad и размещения его в viewWillAppear, но затем он дублирует все метки, которые находятся над scrollView (я предполагаю, потому что он запускается несколько раз ... поэтому он просто накладывает один вид поверх другого). Это также происходит, если вместо того, чтобы поместить весь этот код в viewWillAppear, я поместил его в функцию didFinishPickingMedia. Из-за этого я просто положил все это обратно в viewDidLoad, как в моем коде ниже, и решил, что буду искать помощи у кого-то более опытного.
Я новичок во всех языках программирования (в программировании Вообще), поэтому, пожалуйста, дайте ответы на свои вопросы и объясните их. Кроме того, когда вы публикуете код, пожалуйста, покажите весь класс, чтобы я мог знать, куда поместить включенные вами элементы. Также это позволяет меньше путать с кем-либо еще, кто посещает этот пост с той же проблемой.
Спасибо!
Вот мой код:
import UIKit
struct scrollViewDataStruct {
let title : String?
let image : UIImage?
}
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
var scrollViewData = [scrollViewDataStruct]()
var viewTagValue = 100
var tagValue = 200
var imageTaken = UIImage()
var imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
scrollViewData = [scrollViewDataStruct.init(title: "First", image: #imageLiteral(resourceName: "20191028_220009")),
scrollViewDataStruct.init(title: "Second", image: #imageLiteral(resourceName: "20191028_214433")),
scrollViewDataStruct.init(title: "Third", image: #imageLiteral(resourceName: "20191028_214648")),
scrollViewDataStruct.init(title: "Fourth", image: #imageLiteral(resourceName: "20191028_220457")),
scrollViewDataStruct.init(title: "Fifth", image: #imageLiteral(resourceName: "20191028_220152"))]
scrollView.contentSize.width = self.scrollView.frame.width * CGFloat(scrollViewData.count)
var i = 0
for data in scrollViewData {
let view = CustomView(frame: CGRect(x: 10 + (self.scrollView.frame.width * CGFloat(i)), y: 60, width: self.scrollView.frame.width - 20, height: self.scrollView.frame.height - 90))
view.imageView.image = data.image
view.tag = i + viewTagValue
self.scrollView.addSubview(view)
let label = UILabel(frame: CGRect.init(origin: CGPoint.init(x: 0, y: 20), size: CGSize.init(width: 0, height: 40)))
label.text = data.title
label.font = UIFont.boldSystemFont(ofSize: 30)
label.textColor = UIColor.black
label.sizeToFit()
label.tag = i + tagValue
if i == 0 {
label.center.x = view.center.x
} else {
label.center.x = view.center.x - self.scrollView.frame.width / 2
}
self.scrollView.addSubview(label)
//Stays at bottom
i += 1
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == scrollView {
for i in 0..<scrollViewData.count {
let label = scrollView.viewWithTag(i + tagValue) as! UILabel
let view = scrollView.viewWithTag(i + viewTagValue) as! CustomView
let scrollContentOffset = scrollView.contentOffset.x + self.scrollView.frame.width
let viewOffset = (view.center.x - scrollView.bounds.width / 3) - scrollContentOffset
label.center.x = scrollContentOffset - ((scrollView.bounds.width / 4 - viewOffset) / 2)
}
}
}
@IBAction func takePhotoButton(_ sender: Any) {
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
imageTaken = (info[.originalImage] as? UIImage)!
scrollViewData.append(scrollViewDataStruct.init(title: "Random", image: imageTaken))
imagePicker.dismiss(animated: true, completion: nil)
print(scrollViewData.count)
}
}
class CustomView: UIView {
let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = UIColor.lightGray
imageView.contentMode = .scaleAspectFit
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(imageView)
imageView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
imageView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}