Считываем с plist файла и сохраняем в массив


#1

У меня в plist-файле сохранен рассказ, в виде Dictionary, каждый Item - это “глава”, внутри есть несколько элементов и один из них это опять Dictionary где храниться текст рассказа, в виде отдельных элементов (block1, block2 и т.д.). На рисунке будет более понятно

Потом ниже текст кода где я перебираю словарь и сохраняю в массив - в ходе тестирования я понял что программа не по порядку вытаскивает данные из block1, block2 и т.д… Непонятно как задать, чтобы он сперва вытащил текст из block1, потом block2 и т.д.

    for dictionary in dataArray {    //перебираем полученный Массив по каждому элементу (главе рассказа)
        let storyData = Story()
        let chapterDictionary = dictionary as! NSDictionary
        storyData.chapter = chapterDictionary["chapter"] as! String
        storyData.chapterName = chapterDictionary["chapterName"] as! String
        let textDictionary = chapterDictionary["text"] as! NSDictionary
        for obj in textDictionary {
            storyData.textblocks.append(String(describing: obj.value))
        }
        print(storyData.textblocks)
        self.story.append(storyData)
        pageText = (textDictionary["block1"] as? String)!
    }
}

func getTextToPages () {

let chapterText = story[chapterNumber].textblocks
pageText = (chapterText[pageNumber])

}


#2

Положите ваш рассказ в массив (в файле), тогда всё по порядку будет.


#3

не очень понял - в смысле полностью весь рассказ без разбивки по блокам?
это и так понятно, что можно так сделать, но тут разбивка по блокам не просто так. Она необходима для следующего

  1. первое - если честно я так не понял как текст разбить по экранам, то есть чтобы программа сама определяла размер экрана и выгружала нужное количество текста, и потом после нажатия Next загружала следующий кусок текста
  2. даже если разобраться с первым пунктом - мне нужно разбивка по блокам для подставления определенных слов внутрь текста. Помните сказку про “бабку с дедом у которых был зеленый кадилак”-)? вы мне подсказали как это сделать - вот тут я использую блоки, между которыми будут вставляться слова

#4

Нет, использовать массив:

В массиве всё по порядку лежит, в словаре как получиться.

Тут много вариантов, можно конвертировать текст в pdf и отображать с помощью PDFKit:

import UIKit
import PDFKit

class ViewController: UIViewController {

    override var prefersStatusBarHidden: Bool {
        return true
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let text = try! String(contentsOf: #fileLiteral(resourceName: "File.txt"))
        
        let pdfView = PDFView()
        pdfView.frame = view.frame
        pdfView.displaysPageBreaks = false
        pdfView.usePageViewController(true)
        pdfView.document = PDFDocument(data: textToPDF(text, page: view.frame.size))
        view.addSubview(pdfView)
    }
    
    private func textToPDF(_ text: String, page size: CGSize) -> Data {
        var rect = CGRect(origin: .zero, size: size)
        
        let data = NSMutableData()
        let consumer = CGDataConsumer(data: data)
        let context = CGContext(consumer: consumer!, mediaBox: &rect, nil)!
        
        let attributed = NSAttributedString(string: text, attributes: [.font: UIFont.systemFont(ofSize: 24)])
        let framesetter = CTFramesetterCreateWithAttributedString(attributed as CFAttributedString)
        let path = CGPath(rect: rect.insetBy(dx: 16, dy: 16), transform: nil)
        
        var position = 0
        
        while position < attributed.length {
            context.beginPDFPage(nil)
            
            let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(position, 0), path, nil)
            CTFrameDraw(frame, context)
            let range = CTFrameGetVisibleStringRange(frame)
            position += range.length
            
            context.endPDFPage()
        }
        
        context.closePDF()
        
        return data as Data
    }
}

Что то такое получаеться:


#5

Спасибо за подсказку-)
Сделал массив и все получилось!
с PDFKit тоже попробовал, но сам код не понял, слишком мудренно для меня
не получилось с ним, ну и ладно


#6

А как на такой PDFView добавить кнопку выхода из режима просмотра?


#7

Как на обычный вьюконтроллер.


#8

Так вот не получается что-то.
Добавляю баттон через view.addSubview(view) как и PDFView, привязываю констрейтами, но всё равно почему-то не видно кнопки, какбуд-то PDFView поверх всего… Хотя thumbnailView нормально добавился:

class PDFViewController: UIViewController {
    
    var pdfURL: URL!
    let pdfView = PDFView()
    let thumbnailView = PDFThumbnailView()
    let cancelButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let document = PDFDocument(url: pdfURL) {
            pdfView.document = document
        }
        
        setupPDFView()
        setupThumbnailView()
        setupCancelButton()
        
    }
    
    private func setupPDFView() {
        view.addSubview(pdfView)
        
        pdfView.translatesAutoresizingMaskIntoConstraints = false
        pdfView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        pdfView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        pdfView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        
        pdfView.displayDirection = .horizontal
        pdfView.usePageViewController(true)
        pdfView.pageBreakMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        pdfView.autoScales = true
        
    }
    private func setupThumbnailView() {
        view.addSubview(thumbnailView)
        
        thumbnailView.translatesAutoresizingMaskIntoConstraints = false
        thumbnailView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        thumbnailView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        thumbnailView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        
        pdfView.bottomAnchor.constraint(equalTo: thumbnailView.topAnchor).isActive = true
        thumbnailView.heightAnchor.constraint(equalToConstant: 80).isActive = true
        
        thumbnailView.thumbnailSize = CGSize(width: 60, height: 60)
        thumbnailView.layoutMode = .horizontal
        
        thumbnailView.pdfView = pdfView
    }
    private func setupCancelButton() {
        cancelButton.setImage(#imageLiteral(resourceName: "cancelButtonPDF"), for: .normal)
        view.addSubview(cancelButton)
        
        cancelButton.heightAnchor.constraint(equalToConstant: 20).isActive = true
        cancelButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
        cancelButton.topAnchor.constraint(equalTo: pdfView.topAnchor, constant: 50).isActive = true
        cancelButton.trailingAnchor.constraint(equalTo: pdfView.trailingAnchor, constant: 50).isActive = true
    }
    
}

Результат хочу примерно такой как, кнопка слева вверху:


#9

Может так?

private func setupCancelButton() {
    cancelButton.setImage(#imageLiteral(resourceName: "cancelButtonPDF"), for: .normal)
    view.addSubview(cancelButton)
    cancelButton.translatesAutoresizingMaskIntoConstraints = false
    cancelButton.heightAnchor.constraint(equalToConstant: 20).isActive = true
    cancelButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
    cancelButton.topAnchor.constraint(equalTo: pdfView.topAnchor, constant: 50).isActive = true
    cancelButton.leftAnchor.constraint(equalTo: pdfView.leftAnchor, constant: 50).isActive = true
}

#10

Вы как всегда правы! Напутал я там с констрейтами ))