Почему протокол HTTP разработан в простом тексте путь?

Перейти к обработке изображения, чтобы узнать, как преобразовать UIImage в NSData (что использует Core Data)

Или загрузить с github

Настройка основных данных:

Настройте два объекта: полное разрешение и миниатюру. Полные разрешения - сохранить исходное изображение. Миниатюра для хранения меньшей версии, которая будет использоваться внутри приложения. Например, вы можете использовать меньшую версию в обзоре UICollectionView.

Изображения сохраняются как Binary Data в Core Data. Соответствующим типом в Foundation является NSData. Вернитесь к UIImage с помощью UIImage(data: newImageData)



Установите флажок «Разрешить внешнее хранилище» для полей «Двоичные данные». Это автоматически сохранит изображения в файловой системе, которые ссылаются на них в Core Data

Подключите два объекта, создав отношения «один к одному» между два.

Перейти к редактору en выберите Create NSManagedObjectSubclass. Это будет генерировать файлы с классами, представляющими подклассы управляемых объектов. Они будут отображаться в вашей структуре файла проекта.


Базовая установка ViewController:

Импортируйте следующее:

import UIKit
import CoreData

  • Настройте два UIButtons и UIImageView в построителе интерфейса
  • Создайте две очереди отправки, одну для CoreData и одну для конверсий UIImage

class ViewController: UIViewController {

    // imageview to display loaded image
    @IBOutlet weak var imageView: UIImageView!

    // image picker for capture / load
    let imagePicker = UIImagePickerController()

    // dispatch queues
    let convertQueue = dispatch_queue_create("convertQueue", DISPATCH_QUEUE_CONCURRENT)
    let saveQueue = dispatch_queue_create("saveQueue", DISPATCH_QUEUE_CONCURRENT)

    // moc
    var managedContext : NSManagedObjectContext?


    override func viewDidLoad() {
        super.viewDidLoad()

        imagePickerSetup() // image picker delegate and settings

        coreDataSetup() // set value of moc on the right thread

    }

    // this function displays the imagePicker
    @IBAction func capture(sender: AnyObject) { // button action
        presentViewController(imagePicker, animated: true, completion: nil)
    }

    @IBAction func load(sender: AnyObject) { // button action

        loadImages { (images) -> Void in
            if let thumbnailData = images?.last?.thumbnail?.imageData {
                let image = UIImage(data: thumbnailData)
                self.imageView.image = image
            }
        }
    }
}

Эта функция устанавливает значение managedContext в правильной нити. Поскольку CoreData нуждается в выполнении всех операций в одном NSManagedObjectContext в одном и том же потоке.

extension ViewController {
    func coreDataSetup() {
        dispatch_sync(saveQueue) {
            self.managedContext = AppDelegate().managedObjectContext
        }
    }
}

Расширьте UIViewController, чтобы он соответствовал UIImagePickerControllerDelegate и UINavigationControllerDelegate. Они необходимы для UIImagePickerController.

Создайте функцию настройки, а также создайте функцию делегата imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?)

extension ViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerSetup() {

        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.Camera

    }

    // When an image is "picked" it will return through this function
    func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {

        self.dismissViewControllerAnimated(true, completion: nil)
        prepareImageForSaving(image)

    }
}

Немедленно отпустите UIImagePickerController, иначе приложение будет заморожено.


Обработка изображения:

Вызовите эту функцию внутри imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?).

  • Сначала введите текущую дату с timeIntervalSince1970. Это возвращает NSTimerInterval в секундах. Это хорошо преобразуется в Double. Он будет служить уникальным идентификатором для изображений и как способ их сортировки.
  • Теперь самое время перейти в отдельную очередь и освободить основную очередь. Сначала я использовал dispatch_async(convertQueue), чтобы сделать тяжелый подъем на отдельном потоке.
  • Затем вам нужно преобразовать UIImage в NSData, это делается с помощью UIImageJPEGRepresentation(image, 1). 1 представляет качество, где 1 является самым высоким, а 0 является самым низким. Он возвращает необязательный, поэтому я использовал необязательную привязку.
  • Увеличьте изображение до требуемого размера эскиза, а также преобразуйте его в NSData.

Код:

extension ViewController {

    func prepareImageForSaving(image:UIImage) {

        // use date as unique id
        let date : Double = NSDate().timeIntervalSince1970

        // dispatch with gcd.
        dispatch_async(convertQueue) {

            // create NSData from UIImage
            guard let imageData = UIImageJPEGRepresentation(image, 1) else {
                // handle failed conversion
                print("jpg error")
                return
            }

            // scale image, I chose the size of the VC because it is easy
            let thumbnail = image.scale(toSize: self.view.frame.size)

            guard let thumbnailData  = UIImageJPEGRepresentation(thumbnail, 0.7) else {
                // handle failed conversion
                print("jpg error")
                return
            }

            // send to save function
            self.saveImage(imageData, thumbnailData: thumbnailData, date: date)

        }
    }
}

Эта функция выполняет фактическое сохранение.

  • Перейдите в поток CoreData с помощью dispatch_barrier_sync(saveQueue)
  • Сначала вставьте новый FullRes и новый объект Thumbnail в Контекст управляемого объекта.
  • Задайте значения
  • Установите связь между FullRes и Thumbnail
  • Используйте do try catch для попытки сохранения
  • Обновите управляемый объект Context, чтобы освободить память

Используя dispatch_barrier_sync(saveQueue), мы уверены, что можем безопасно хранить новое изображение и что новые сэки или нагрузки будут ждать, пока это не закончится.

Код:

extension ViewController {

    func saveImage(imageData:NSData, thumbnailData:NSData, date: Double) {

        dispatch_barrier_sync(saveQueue) {
            // create new objects in moc
            guard let moc = self.managedContext else {
                return
            }

            guard let fullRes = NSEntityDescription.insertNewObjectForEntityForName("FullRes", inManagedObjectContext: moc) as? FullRes, let thumbnail = NSEntityDescription.insertNewObjectForEntityForName("Thumbnail", inManagedObjectContext: moc) as? Thumbnail else {
                // handle failed new object in moc
                print("moc error")
                return
            }

            //set image data of fullres
            fullRes.imageData = imageData

            //set image data of thumbnail
            thumbnail.imageData = thumbnailData
            thumbnail.id = date as NSNumber
            thumbnail.fullRes = fullRes

            // save the new objects
            do {
                try moc.save()
            } catch {
                fatalError("Failure to save context: \(error)")
            }

            // clear the moc
            moc.refreshAllObjects()
        }
    }
}

Для загрузки изображения:

extension ViewController {

    func loadImages(fetched:(images:[FullRes]?) -> Void) {

        dispatch_async(saveQueue) {
            guard let moc = self.managedContext else {
                return
            }

            let fetchRequest = NSFetchRequest(entityName: "FullRes")

            do {
                let results = try moc.executeFetchRequest(fetchRequest)
                let imageData = results as? [FullRes]
                dispatch_async(dispatch_get_main_queue()) {
                    fetched(images: imageData)
                }
            } catch let error as NSError {
                print("Could not fetch \(error), \(error.userInfo)")
                return
            }
        }
    }
}

Функции, используемые для масштабирования изображения:

extension CGSize {

    func resizeFill(toSize: CGSize) -> CGSize {

        let scale : CGFloat = (self.height / self.width) < (toSize.height / toSize.width) ? (self.height / toSize.height) : (self.width / toSize.width)
        return CGSize(width: (self.width / scale), height: (self.height / scale))

    }
}

extension UIImage {

    func scale(toSize newSize:CGSize) -> UIImage {

        // make sure the new size has the correct aspect ratio
        let aspectFill = self.size.resizeFill(newSize)

        UIGraphicsBeginImageContextWithOptions(aspectFill, false, 0.0);
        self.drawInRect(CGRectMake(0, 0, aspectFill.width, aspectFill.height))
        let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }

}

30
задан Morgan Cheng 26 December 2008 в 02:36
поделиться

7 ответов

причина это является и техническим и историческое, то, что текстовые протоколы почти всегда предпочитаются в мире Unix.

ну, это не действительно причина, но шаблон . Объяснение позади этого - то, что текстовые протоколы позволяют, Вы к видите , что продолжается в сети, просто выведя все, что проходит. Вам не нужен специализированный анализатор, как Вам нужно для TCP/IP. Это помогает отладить и легче поддержать.

Не только HTTP, но и много протоколов являются базирующимся текстом (например, FTP, POP3, SMTP, IMAP).

Вы могли бы хотеть смотреть на Искусство Программирования Unix для намного более подробного объяснения этой вещи Unix.

55
ответ дан 27 November 2019 в 23:05
поделиться

Много протоколов интернет-приложения используют более или менее простой текст для протокола (см. FTP, POP, SMTP, и т.д.).

Это делает совместимость и поиск и устранение неисправностей намного легче.

9
ответ дан 27 November 2019 в 23:05
поделиться

HTTP обозначает "Протокол передачи гипертекста".

Это было первоначально создано как способ вручить текстовые документы, следовательно основанный на тексте протокол.

то, Что мы делаем с HTTP теперь, далеко вне его исходного намерения.

8
ответ дан 27 November 2019 в 23:05
поделиться

С HTTP содержание из запроса является почти всегда порядками величины, больше, чем протокол наверху. Преобразование протокола в двоичную единицу сохранило бы очень мало пропускной способности и легкий debugability, который текстовый протокол предлагает легко козыри незначительные сбережения пропускной способности протокола двоичной синхронной передачи данных.

18
ответ дан 27 November 2019 в 23:05
поделиться

Как с раздел RFC 2616 3.7.1 для HTTP 1.1, ключевой идентификатор к строке команды или заголовка является текстовым разрывом строки CRLF; основанные на тексте прикладные протоколы помогают выполнить разговор (для поиска и устранения неисправностей) просто с клиентом Telnet. Это также помогает программировать с ReadLine () строки совпавшего текста и вызовы.

повреждение параметра CRLF также дает почти неограниченные abitrary расширения заголовка в отличие от фиксированного размера TCP или заголовки IP где твердые коды разрядными смещениями.

5
ответ дан 27 November 2019 в 23:05
поделиться

Таким образом, легче "считать" трафик или создать клиент или сервер?

можно дебатировать, помогает ли это на самом деле , но конечно который был намерением.

3
ответ дан 27 November 2019 в 23:05
поделиться

Исторически, все это начинает с RFC822 (СТАНДАРТ ДЛЯ ФОРМАТА ИНТЕРНЕТ-ТЕКСТОВЫХ СООБЩЕНИЙ ARPA), чья последняя версия является RFC5322 (интернет-Формат сообщения). SMTP (RFC 821) был одним из самого популярного протокола на основе RFC822. И, HTTP был подтвержден SMTP (Ваш почтовый протокол).

1
ответ дан 27 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: