Swift 3: Загрузить изображение в облачный [дубликат]

Некоторые статистические данные, связанные с этим известным вопросом с двойной точностью.

При добавлении всех значений ( a + b ) с шагом 0,1 (от 0,1 до 100) имеем ~ 15% вероятность ошибки точности. Обратите внимание, что ошибка может привести к несколько большим или меньшим значениям. Вот несколько примеров:

0.1 + 0.2 = 0.30000000000000004 (BIGGER)
0.1 + 0.7 = 0.7999999999999999 (SMALLER)
...
1.7 + 1.9 = 3.5999999999999996 (SMALLER)
1.7 + 2.2 = 3.9000000000000004 (BIGGER)
...
3.2 + 3.6 = 6.800000000000001 (BIGGER)
3.2 + 4.4 = 7.6000000000000005 (BIGGER)

При вычитании всех значений ( a - b , где a> b ) с шагом 0,1 (от 100 до 0,1), мы имеем вероятность 34% точности. Вот несколько примеров:

0.6 - 0.2 = 0.39999999999999997 (SMALLER)
0.5 - 0.4 = 0.09999999999999998 (SMALLER)
...
2.1 - 0.2 = 1.9000000000000001 (BIGGER)
2.0 - 1.9 = 0.10000000000000009 (BIGGER)
...
100 - 99.9 = 0.09999999999999432 (SMALLER)
100 - 99.8 = 0.20000000000000284 (BIGGER)

* 15% и 34% действительно огромны, поэтому всегда используйте BigDecimal, когда точность имеет большое значение. С 2 десятичными цифрами (шаг 0,01) ситуация несколько ухудшается (18% и 36%).

5
задан Pedro de Sá 1 May 2016 в 16:59
поделиться

3 ответа

По моему опыту, единственный способ сохранить загрузку UIImage в качестве CKAsset:

  1. временно сохранить изображение на диск
  2. Создать CKAsset
  3. Удалить временный файл

let data = UIImagePNGRepresentation(myImage); // UIImage -> NSData, see also UIImageJPEGRepresentation
let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
do {
    try data!.writeToURL(url, options: [])
} catch let e as NSError {
    print("Error! \(e)");
    return
}
newUser["photo"] = CKAsset(fileURL: url)

// ...

publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in
    // Delete the temporary file
    do { try NSFileManager.defaultManager().removeItemAtURL(url) }
    catch let e { print("Error deleting temp file: \(e)") }

    // ...
}

Несколько месяцев назад я опубликовал отчет об ошибке, запрашивающий возможность инициализации CKAsset из памяти NSData, но это еще не сделано.

8
ответ дан Santa Claus 28 August 2018 в 22:55
поделиться

Это версия Objective C о том, как сохранить изображение в Cloudkit

. Это заняло довольно много места, поскольку информации не так много, но это работает

  if([results count] <= 0) {



            NSLog(@"this Record doesnt exist so add it ok!! %@", error);

            CKRecordID *wellKnownID = [[CKRecordID alloc]
                                       initWithRecordName:idString];


            CKRecord *entitiesName = [[CKRecord alloc] initWithRecordType:@"mySavedDetails"
                                                             recordID:wellKnownID];


            [entitiesName setObject:idString
                         forKey:@"myDetailsId"];

            [entitiesName setObject:self.myName.text
                         forKey:@"myName"];



    if (myUIImage.image != nil)
                 {
                     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                                          NSUserDomainMask, YES);
                     NSString *documentsDirectory = [paths objectAtIndex:0];
                     NSString* path = [documentsDirectory stringByAppendingPathComponent:
                                       @"test.png" ];
                     NSData* data = UIImagePNGRepresentation(myUIImage.image.image);
                     [data writeToFile:path atomically:YES];

    //so we get the full path of the uiimage

                     NSLog(@"Path details %@",path);


                     NSURL* myImagePath = nil;
                     myImagePath =
                     [[NSBundle mainBundle] URLForResource:path
                                             withExtension:@"png"];



 //here we change the path of Image which is a string to a URL
                     NSURL *yourURL = [NSURL fileURLWithPath:path];

                     CKAsset* myImageAsset = nil;
                     myImageAsset =
                     [[CKAsset alloc] initWithFileURL:yourURL];




                [entitiesName setObject: myImageAsset
                              forKey:@"myImage"];




                [publicDatabase saveRecord: entitiesName
                          completionHandler:^(CKRecord *savedState, NSError *error) {
                              if (error) {
                                  NSLog(@"ERROR SAVING: %@", error);
                              }


                          }];



                 }




            }
2
ответ дан Graham 28 August 2018 в 22:55
поделиться

Я делал что-то совсем другое: я создал класс, который вы можете использовать в нескольких местах, и благодаря тому, что Swift имеет повторную инициализацию, которая работает (в отличие от C ++), она очищается после себя:

//
//  ImageAsset.swift
//

import CloudKit
import UIKit

class ImageAsset {

    let image:UIImage

    var url:NSURL?

    var asset:CKAsset? {
        get {
            let data = UIImagePNGRepresentation(self.image)
            self.url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
            if let url = self.url {
                do {
                    try data!.writeToURL(url, options: [])
                } catch let e as NSError {
                    print("Error! \(e)")
                }
                return CKAsset(fileURL: url)
            }
            return nil
        }
    }

    init(image:UIImage){
        self.image = image
    }

    deinit {
        if let url = self.url {
            do {
                try NSFileManager.defaultManager().removeItemAtURL(url) }
            catch let e {
                print("Error deleting temp file: \(e)")
            }
        }
    }


}

Вот блок-тест, который его использует (предполагается, что в тестовой цели есть изображение с именем секундомер):

//
//  ImageExtensionTests.swift
//

import CloudKit
import XCTest
@testable import BudgetImpactEstimator

class ImageExtensionTests: XCTestCase {

    let testImageName = "stopwatch" // provide the name of an image in test bundle
    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testConvertingImageToAsset() {
        guard let image = UIImage(named: self.testImageName) else {
            XCTFail("failed to load image")
            return
        }
        let imageAsset = ImageAsset(image: image)
        XCTAssertNotNil(imageAsset)

        guard let asset = imageAsset.asset else {
            XCTFail("failed to get asset from image")
            return
        }

        print("constructed asset: \(asset)")
    }


}

Первоначально собирался сделать это как расширение на UIImage, но затем определить заставил меня перейти к классу.

2
ответ дан Rob 28 August 2018 в 22:55
поделиться
Другие вопросы по тегам:

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