質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS 9

iOS 9は、アップル社のモバイルOSであるiOSシリーズのバージョン。特徴として検索機能の強化、Siriの機能改良、iPad向けマルチタスクなどがあります。マルチウィンドウ機能をサポートし、iPad向けマルチタスクもサポートされています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

3回答

3653閲覧

複数のUIImageを一括でカメラロールに保存したい

kawakam

総合スコア13

iOS 9

iOS 9は、アップル社のモバイルOSであるiOSシリーズのバージョン。特徴として検索機能の強化、Siriの機能改良、iPad向けマルチタスクなどがあります。マルチウィンドウ機能をサポートし、iPad向けマルチタスクもサポートされています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

1グッド

1クリップ

投稿2015/11/01 12:26

最近プログラミングを始めた者で、初めての投稿になります。どうぞ宜しくお願い致します。

ネットから取得した画像データを一括でiPhoneのカメラロールに保存するアプリを作っております。
画像データ自体は何とか取得が出来て、空のUIImage型の配列に取得した順番で追加出来たのですが、それをカメラロールに保存する作業でエラーが出てしまっています。
40枚近いデータがあるはずなのですが、毎回6枚ほどしか保存できていない状況です。配列自体をprint()で出力してみても、ちゃんと40枚前後のデータがデバックエリアに出力される為、配列に保存すること自体は出来ていると思います。

エラー文にある「リソースがビジー」とは、配列のデータをバッファ(?)に書き込んだあと、そのデータを保存する前にバッファが上書きされているということなのでしょうか…?上書きのタイミングが早すぎて保存が追いついていない…?

自分なりに調べては見たのですがどうしても以下のエラーが解決できません。
何卒お力添えいただきますよう、心よりお願いいたします。

###エラー文
Xcodeで出力されたエラー文です

NSLocalizedFailureReason=There was a problem writing this asset because the writing resources are busy.}}, NSLocalizedDescription=Write busy, NSLocalizedRecoverySuggestion=Try to write again, NSLocalizedFailureReason=There was a problem writing this asset because the writing resources are busy.}

###ソースコード
どうやらこのメソッド部分ででエラーが出てしまう様です。imageManaインスタンスのプロパティであるimages配列に画像データが入っていて、.imgの部分がUIimage型の要素です。

カメラロールに保存するメソッドは以下のURLを参考にしました。
http://qiita.com/kitanoow/items/995d254fa6cd89f066cb

func saveAllImages() {
for fetch in imageMana.images {
UIImageWriteToSavedPhotosAlbum(fetch.img, self, "image:didFinishSavingWithError:contextInfo:", nil)
}
}

###補足情報
質問者としても右も左も分からない状態で、「質問者として何々が書き足りない」「この情報だけじゃエラーの原因が分からない」など、そのような点もご指摘頂けたらありがたいです。

kizahashi👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ストレージ容量不足だけでなく、別の原因で複数同時書き込みが失敗する可能性があるのですね。
1枚ずつ画像を保存するなら、例えば
保存中の画像を保持した配列を以下のようなプロパティで定義し、
```Swift
var savingImages : [UIImage] = []

以下のような保存メソッドを作成し ```Swift func saveImage() { if savingImages.count > 0 { UIImageWriteToSavedPhotosAlbum(savingImages[0], self, "image:didFinishSavingWithError:contextInfo:", nil) savingImages.removeAtIndex(0) } else { print("all completed.") } } func image(image: UIImage, didFinishSavingWithError error: NSError!, contextInfo: UnsafeMutablePointer<Void>) { if error != nil { print("save error \(image)") print(error.description) } else { print("save completed \(image)") saveImage() } }

保存を開始したいところで、保存したいイメージの配列をsavingImagesに格納した上で、saveImage()を呼び出せば良いです。

投稿2015/11/02 16:42

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kawakam

2015/11/03 07:37

お陰様で無事解決しました!質問自体初めての経験で投稿時は非常に不安でしたが、丁寧に解説して頂けてとても感謝しています。教えていただいたsampleのソースコードも非常に助かりました。fuzzballさんTakeOneさん本当にありがとうございました!
guest

0

私も以前同様の問題に遭遇し、調べたことがあります。

UIImageWriteToSavedPhotosAlbumは非同期関数なので、画像の書き込みが完了する前にその画像にアクセスするとエラーになると思いますが、複数の新しい画像(別々の画像)の同時書き込みはできるはずです。私が調べた限り、このエラーが発生するのは空きストレージ量が不足している場合です。

設定アプリの[一般]-[ストレージとiCloudの使用状況]で、使用可能な空きストレージ量を確認してみてください。
私の感触的には、一度に保存しようとしている画像の合計データサイズの2倍以上ストレージの空きがないとエラーが発生するケースが出てくる感じです。(あくまで感触であり、公式のドキュメントに書かれているような正確な情報ではありません。)

なお、ストレージの空きを増やすために、写真アプリで写真を削除するだけではダメです。
写真アプリで写真を削除した場合、実際には「最近削除した項目」のフォルダに写真が移動するだけで空きストレージ量は増えません。「最近削除した項目」のフォルダで[選択]ボタンをタップして[全て削除]を実施することで空きストレージ量が増えます。この点も、今回の問題が空きストレージ量の問題ではないと勘違いしがちになるところです。(毎回不要な写真を削除してからテストしているので空きストレージ量は問題ないと思いがち)

ただ、このように複数の画像を一度に同時保存しようとすると、同時処理のために同時に必要なストレージが増えるのも確かで、空き容量が少ない状態でもできるだけ保存できるようにしたいなら、保存完了通知を受信しながら1枚ずつ保存する処理もありだと思います。

同時保存するなら、どの画像が保存成功し、どの画像が保存失敗したかユーザーにわかるようにし、保存失敗した分については、ユーザーが不要なデータを整理してから、失敗した分の保存を後で再実行できるようにするユーザーインターフェースを合わせて作る必要があると思います。

投稿2015/11/02 02:45

編集2015/11/02 02:49
TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2015/11/02 05:25

ごく小さな画像(10x10pixel)を10枚連続で保存しようとしても同様のエラーが発生しますので、空き容量の問題では無いと思います。
TakeOne

2015/11/02 06:26

私の場合、3414x2560サイズのJPEG画像(約2MB)を60枚連続(合計120MB)でUIImageWriteToSavedPhotosAlbumを実行しましたが、空きストレージが320MBある時はエラーは発生せず、空きが200MBの時は60枚中1〜2枚で質問のエラーメッセージのエラーが発生しました。また、空きがない場合は、ほとんどの画像が同様のエラーになりました。 このことから、このエラーは空き容量の問題が影響していると考えましたが、どこか正式なドキュメントに記載された仕様を説明したものではなく、こちらの環境で調査した結果を参考にお伝えしたものです。fuzzballさんがおっしゃるように、同時保存を実行した時にエラーとなる要因が空き容量の問題とは別に何かあるのかもしれません。
fuzzball

2015/11/02 07:10

「空き容量の問題では無い」ではなく「空き容量の問題だけではない」ということですね。検証結果を否定するような書き方をして申し訳ありませんでした。
kawakam

2015/11/02 14:04

お二人ともコメント本当にありがとうございます。ストレージの空きを増やす為に最近消去した項目も全て消去してから試してみたのですが、同様のエラーが表示されてしまいました。なので今回はお二人に指摘して頂いた非同期通信の部分に原因がある可能性が高そうです。しかし今後別の保存処理などで同じ様なエラーが出た時にはTakeOneさんにご指摘頂いたストレージの容量不足でのエラーを真っ先に疑ってみたいと思います。 非同期通信ということで、画像を保存する(書き込む?)処理の終了を待たずに次の画像を読み込んでしまうのが原因、ということはお二人のコメントから理解しました。そこでそれを回避する為にif文を用いて、1つの画像の読み取りと書き込みの処理が終わるタイミングで一旦保存処理の動作を止めてやる(?)ことの必要性も理解したつもりなのですが、恥ずかしながらerror処理の文の書き方が分からない状態でして… if error != nil { //エラー → 止める or リトライ or スキップ } else { //正常終了 → 次の画像へ } このif文は、保存処理のメソッド内に書けば良いのでしょうか? それともこのif文の中に画像を保存するメソッドを記述すべきなのでしょうか。 参考書などでSwiftやプログラミングの基礎の基礎は学んだのですが、error処理等の知識がまだ追いついていない状況です。ネット等でも検索してみたのですが、今の自分が理解出来る範囲でerror処理を解説してくれている記事を探し当てることが出来ませんでした。厚かましいお願いにはなるのですが、この処理をどの様に記述すれば良いかアドバイス頂けるとありがたいです。重ね重ね申し訳ありません。
guest

0

UIImageWriteToSavedPhotosAlbumは非同期関数ですので、
正常終了にせよエラーにせよ終了を待たないといけません。
(参照された記事は正常終了処理が書かれていませんね)

swift

1if error != nil { 2 //エラー → 止める or リトライ or スキップ 3} else { 4 //正常終了 → 次の画像へ 5}

投稿2015/11/02 00:36

編集2015/11/02 05:11
fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問