質問編集履歴

2

退会済みユーザー

退会済みユーザー

2017/03/13 09:21  投稿

deviceから撮影した写真(imageBuffer)がCoreDataに保存できない
###前提・実現したいこと
swiftでデバイスカメラで撮影した写真をCoreDataに保存するアプリを作っています。
撮影は、NSTimerで5秒間に1回BracketedStillImageSettingsで撮影するようにしています。
が、imageBufferがCoreDataに保存できません。
###該当のソースコード
```Swift3
// ViewController
// 撮影するコード
if let output = myImageOutput {
DispatchQueue.global().async {
let connection = output.connection(withMediaType: AVMediaTypeVideo)
let settings = [-2.0, 0.0, 2.0].map {
(bias: Float) -> AVCaptureAutoExposureBracketedStillImageSettings in AVCaptureAutoExposureBracketedStillImageSettings.autoExposureSettings(withExposureTargetBias: bias)
}
output.captureStillImageBracketAsynchronously(from: connection, withSettingsArray: settings, completionHandler: { (imageBuffer, settings, error) in
//print("imageBuffer: \(imageBuffer)")
if error == nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageBuffer)!
if let image = UIImage(data: imageData) {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) }
}
else {
print("error while capturing still image: \(error)")
}
})
}
}
// 毎フレームをCoreDataに保存する処理
func writeBuffer(imageBuffer: CVPixelBuffer) -> NSData {
CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
let bufferSize = CVPixelBufferGetDataSize(imageBuffer)
let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
let colorSpace = CGColorSpaceCreateDeviceRGB()
var data: NSData = NSData(bytes: baseAddress, length: bufferSize)
CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
let myContext: NSManagedObjectContext = appDelegate.managedObjectContext
let myEntity: NSEntityDescription! = NSEntityDescription.entity(forEntityName: "ImageData", in: myContext)
let newData = ImageData(entity: myEntity, insertInto: myContext)
newData.imageData? = data
do {
try myContext.save()
} catch {
print(error)
}
return data
}
```
###試したこと
プロジェクト作成時にUse CoreDataにチェック入れてなかったので、新しいファイル(CoreData > DataModel)を作成し、.xcdatamodeledファイルを追加しました。
EntityはimageDataにし、TypeはBinary Dataです。
その後、Editor > Create NSManagedObject Subclassでエンティティモデルコードを生成しました。
そのあと、appDelegateに以下のコードを書き加えました
```ここに言語を入力
lazy var applicationDocumentsDirectory: NSURL = {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1] as NSURL
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = Bundle.main.url(forResource: "ImageDataBase", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
@available(iOS 10.0, *)
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "coredataTest")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
if #available(iOS 10.0, *) {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
} else {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
}
```
###補足情報(言語/FW/ツール等のバージョンなど)
print("imageBuffer: \(imageBuffer)")とすると、imageBuffuerの中には値も入っています。
CoreDataに保存できているかどうかの確認は、Window>Devicesから実機simulator、該当アプリを選択して表示されるフォルダに特に何も追加されていないので保存できていないと判断しました。
CoreDataの使い方が間違っているのかもしれませんが、原因が何かもわかりません。
ご教授宜しくお願いします
  • Swift

    13984 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

1 UIImageへの変換はできた

退会済みユーザー

退会済みユーザー

2017/03/10 18:01  投稿

deviceから撮影した写真(imageBuffer)がCoreDataに保存できない
###前提・実現したいこと
swiftでデバイスカメラで撮影した写真をCoreDataに保存するアプリを作っています。
撮影は、NSTimerで5秒間に1回BracketedStillImageSettingsで撮影するようにしています。
実機でビルドすると、撮影はできているのですが(シャッター音が鳴るので)、以下のエラーが出てとまってしまいます。
###発生している問題・エラーメッセージ
```
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:] - Not a jpeg sample buffer.'
```
が、imageBufferがCoreDataに保存できません。
###該当のソースコード
```Swift3
// ViewController
// 撮影するコード
if let output = myImageOutput {
           DispatchQueue.global().async {
               let connection = output.connection(withMediaType: AVMediaTypeVideo)
               let settings = [-2.0, 0.0, 2.0].map {
                   (bias: Float) -> AVCaptureAutoExposureBracketedStillImageSettings in                   AVCaptureAutoExposureBracketedStillImageSettings.autoExposureSettings(withExposureTargetBias: bias)
               }
               output.captureStillImageBracketAsynchronously(from: connection, withSettingsArray: settings, completionHandler: { (imageBuffer, settings, error) in
                     //print("imageBuffer: \(imageBuffer)")
                   if error == nil {
                       let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageBuffer)!                   
                    if let image = UIImage(data: imageData) {
                     UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)                                          }
                   }
                   else {
                       print("error while capturing still image: \(error)")
                   }                   
               })
           }
       }
// 毎フレームをCoreDataに保存する処理
 func writeBuffer(imageBuffer: CVPixelBuffer) -> NSData {
       CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
       let bufferSize = CVPixelBufferGetDataSize(imageBuffer)
       let width = CVPixelBufferGetWidth(imageBuffer)
       let height = CVPixelBufferGetHeight(imageBuffer)
       let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
       let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
       let colorSpace = CGColorSpaceCreateDeviceRGB()
       var data: NSData = NSData(bytes: baseAddress, length: bufferSize)
       CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
       let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
       let myContext: NSManagedObjectContext = appDelegate.managedObjectContext
       let myEntity: NSEntityDescription! = NSEntityDescription.entity(forEntityName: "ImageData", in: myContext)
       let newData = ImageData(entity: myEntity, insertInto: myContext)
       newData.imageData? = data
       do {
           try myContext.save()     
       } catch {
           print(error)
       }
       return data
   }
```
###試したこと
プロジェクト作成時にUse CoreDataにチェック入れてなかったので、新しいファイル(CoreData > DataModel)を作成し、.xcdatamodeledファイルを追加しました。
EntityはimageDataにし、TypeはBinary Dataです。
その後、Editor > Create NSManagedObject Subclassでエンティティモデルコードを生成しました。
そのあと、appDelegateに以下のコードを書き加えました
```ここに言語を入力
lazy var applicationDocumentsDirectory: NSURL = {
       let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
       return urls[urls.count-1] as NSURL
   }() 
   lazy var managedObjectModel: NSManagedObjectModel = {
       // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
       let modelURL = Bundle.main.url(forResource: "ImageDataBase", withExtension: "momd")!
       return NSManagedObjectModel(contentsOf: modelURL)!
   }()
   lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
       // Create the coordinator and store
       let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
       let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
       var failureReason = "There was an error creating or loading the application's saved data."
       do {
           try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
       } catch {
           // Report any error we got.
           var dict = [String: AnyObject]()
           dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
           dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
           dict[NSUnderlyingErrorKey] = error as NSError
           let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
           NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
           abort()
       }
       
       return coordinator
   }()
   
   lazy var managedObjectContext: NSManagedObjectContext = {
       let coordinator = self.persistentStoreCoordinator
       var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
       managedObjectContext.persistentStoreCoordinator = coordinator
       return managedObjectContext
   }()
   @available(iOS 10.0, *)
   lazy var persistentContainer: NSPersistentContainer = {
       let container = NSPersistentContainer(name: "coredataTest")
       container.loadPersistentStores(completionHandler: { (storeDescription, error) in
           if let error = error as NSError? {
               fatalError("Unresolved error \(error), \(error.userInfo)")
           }
       })
       return container
   }()
   
   func saveContext () {
       if #available(iOS 10.0, *) {
           let context = persistentContainer.viewContext
           if context.hasChanges {
               do {
                   try context.save()
               } catch {
                   let nserror = error as NSError
                   fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
               }
           }
       } else {
           if managedObjectContext.hasChanges {
               do {
                   try managedObjectContext.save()
               } catch {
                   let nserror = error as NSError
                   NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
                   abort()
               }
           }
       }
   }
```
###補足情報(言語/FW/ツール等のバージョンなど)
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageBuffer)!                   
                    if let image = UIImage(data: imageData) {
                     UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
を消すと、CoreDataに保存は出来ていませんが、エラー無く撮影を終えることが出来ます。
このときprint("imageBuffer: \(imageBuffer)")とすると、imageBuffuerの中には値も入っています。
print("imageBuffer: \(imageBuffer)")とすると、imageBuffuerの中には値も入っています。
CoreDataに保存できているかどうかの確認は、Window>Devicesから実機simulator、該当アプリを選択して表示されるフォルダに特に何も追加されていないので保存できていないと判断しました。
CoreDataの使い方が間違っているのかもしれませんが、原因が何かもわかりません。
ご教授宜しくお願いします
  • Swift

    13984 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る