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

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

ただいまの
回答率

87.79%

画像をサーバーにアップロードできない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,332
退会済みユーザー

退会済みユーザー

Swiftアプリで、フォトライブラリーやカメラから画像をPythonのDjangoで作ったサーバーにアップロードしたいです。
Swiftでコードを書き、実機(自分のiPHone)で実行すると、

2017-07-20 19:35:47.953836 Swift_App[250:6064] [Generic] Creating an image format with an unknown type is an error
fatal error: unexpectedly found nil while unwrapping an Optional value
2017-07-20 19:35:49.270708 Kenshin_Swift[250:6064] fatal error: unexpectedly found nil while unwrapping an Optional value


とエラーが出ました。エラーが出た時、

libswiftCore.dylib`function signature specialization <preserving fragile attribute, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never:
    0x10032d184 <+0>:   stp    x26, x25, [sp, #-80]!
    0x10032d188 <+4>:   stp    x24, x23, [sp, #16]
    0x10032d18c <+8>:   stp    x22, x21, [sp, #32]
    0x10032d190 <+12>:  stp    x20, x19, [sp, #48]
    0x10032d194 <+16>:  stp    x29, x30, [sp, #64]
    0x10032d198 <+20>:  add    x29, sp, #64              ; =64 
    0x10032d19c <+24>:  mov    x19, x6
    0x10032d1a0 <+28>:  mov    x20, x5
    0x10032d1a4 <+32>:  mov    x21, x4
    0x10032d1a8 <+36>:  mov    x22, x3
    0x10032d1ac <+40>:  mov    x23, x2
    0x10032d1b0 <+44>:  mov    x24, x1
    0x10032d1b4 <+48>:  mov    x25, x0
    0x10032d1b8 <+52>:  adr    x8, #936936               ; protocol descriptor for Swift.CVarArg + 88
    0x10032d1bc <+56>:  nop    
    0x10032d1c0 <+60>:  add    x0, x8, #16               ; =16 
    0x10032d1c4 <+64>:  movz   w1, #0x28
    0x10032d1c8 <+68>:  orr    w2, wzr, #0x7
    0x10032d1cc <+72>:  bl     0x10032d4b0               ; rt_swift_allocObject
    0x10032d1d0 <+76>:  mov    x8, x0
    0x10032d1d4 <+80>:  stp    x22, x21, [x8, #16]
    0x10032d1d8 <+84>:  strb   w20, [x8, #32]
    0x10032d1dc <+88>:  str    w19, [x8, #36]
    0x10032d1e0 <+92>:  adr    x3, #241008               ; partial apply forwarder for Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never).(closure #2)
    0x10032d1e4 <+96>:  nop    
    0x10032d1e8 <+100>: mov    x0, x25
    0x10032d1ec <+104>: mov    x1, x24
    0x10032d1f0 <+108>: mov    x2, x23
    0x10032d1f4 <+112>: mov    x4, x8
    0x10032d1f8 <+116>: bl     0x100220b80               ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
->  0x10032d1fc <+120>: brk    #0x1


とPCの画面に出ました。
実機の方はアップロードしたい画像が出て固まったままです。
アップロードを行う部分は

//
//  PhotoController.swift
//  Kenshin_Swift
//
//  Created by 蓮池由梨 on 2017/06/11.
//  Copyright © 2017年 蓮池由梨. All rights reserved.
//

import Foundation
import MobileCoreServices
import UIKit
class PhotoController:UIViewController,UINavigationControllerDelegate,UIImagePickerControllerDelegate{


    @IBOutlet weak var myActivityIndicator: UIActivityIndicatorView!
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var myImageView: UIImageView!
    private var imagePicker:UIImagePickerController!
    var textField: UITextField!

    @IBAction func uploadButtonTapped(_ sender: Any) {
        myImageUploadRequest()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        label.adjustsFontSizeToFitWidth = true
        label.minimumScaleFactor = 0.5
        label.text = "Tap the PhotoSelect or Camera to upload a picture"
        myActivityIndicator.hidesWhenStopped = true
        textField = UITextField()
     }

    @IBAction func PhotoSelect(_ sender: Any) {
        let myPickerController = UIImagePickerController()
        myPickerController.delegate = self;
        myPickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary

        self.present(myPickerController, animated: true, completion: nil)

    }

    @IBAction func Camera(_ sender: Any) {
        let sourceType:UIImagePickerControllerSourceType = UIImagePickerControllerSourceType.camera
        // カメラが利用可能かチェック
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera){
            // インスタンスの作成
            let cameraPicker = UIImagePickerController()
            cameraPicker.sourceType = sourceType
            cameraPicker.delegate = self
            self.present(cameraPicker, animated: true, completion: nil)

        }
        else{
            label.text = "error"

        }

    }


    // 撮影が完了時した時に呼ばれる
    func imagePickerController(_ imagePicker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
            myImageView.contentMode = .scaleAspectFit
            myImageView.image = pickedImage

        }

        //閉じる処理
        imagePicker.dismiss(animated: true, completion: nil)
        label.text = "Tap the Send to save a picture"

    }

    // 撮影がキャンセルされた時に呼ばれる
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
        label.text = "Canceled"
    }



//
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    //画像のアップロード処理
    func myImageUploadRequest(){

        //myUrlにはphpファイルのアドレスを入れる
        let myUrl = NSURL(string:"http://localhost:8000/admin/accounts/post/42/change/");

        let request = NSMutableURLRequest(url:myUrl! as URL)
        request.httpMethod = "POST"


        let boundary = generateBoundaryString()

        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        let imageData = UIImageJPEGRepresentation(self.myImageView.image!, 1)
        print("here")
        print(self.myImageView.image)

        if(imageData==nil) { return; }
        var name = ""
        if let text = textField.text {
            name = text
        }
        let postString =  "name=\(name)"
//        let postString = "name=\(textField.text!)"
        request.httpBody = postString.data(using: .utf8)

        //myActivityIndicator.startAnimating();

        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, response, error in
            if error != nil {
                print("error=\(error)")
                return
            }
            // レスポンスを出力
            print("******* response = \(response)")
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print("****** response data = \(responseString!)")

            DispatchQueue.main.async(execute: {
                //アップロード完了
            });
        }
        task.resume()

    }


    func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().uuidString)"
}



}


データがnilであるとエラーが出ていますが、
どこでなぜnilとなってしまうのでしょうか?
ブレークポイントを貼ると

let myUrl = NSURL(string:"http://localhost:8000/admin/accounts/post/42/change/");


で落ちていることがわかりました。また、その時のデータ型は
イメージ説明
であることがわかりました。
何が原因でどう直せば良いのでしょうか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2017/07/20 22:42

    なんででしょう。。。?コードは一切変えていないのですが。。。

    キャンセル

  • ykws

    2017/07/20 22:44

    エラーメッセージはボタンをタップする前に表示されていませんか?

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/07/21 21:35

    はい、アルバムを開き画像を選択し、アプリの画面に画像を選択した時に[Generic] Creating an image〜のエラーメッセージが出ています。サーバーに画像を送るSendボタンを送る前にはエラーがもう既に出ていますね!

    キャンセル

回答 2

checkベストアンサー

0

var textField: UITextField!

このtextFieldがnilなんですね。

@IBOutletしてStoryboardなりXibからtextFieldとつなぐか
viewDidLoadなどの初期化のタイミングでtextField = UITextField() などしてみてください。

もしくは

var name = ""
if let text = textField.text {
 name = text
} 
let postString =  "name=\(name)"

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/02 13:01

    ありがとうございます!なるほど、そこが問題だったのですね!
    質問文に記載したようにPhotoControllerを書き換えたのですが、
    今度は、
    error=Optional(Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSUnderlyingError=0x600000441320 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}, NSErrorFailingURLStringKey=http://localhost:8000/admin/accounts/post/42/change/, NSErrorFailingURLKey=http://localhost:8000/admin/accounts/post/42/change/, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.})
    とエラーが出てしまいました。
    このエラーはどの部分を見れば直せるものなのでしょうか?

    キャンセル

  • 2017/08/02 13:19

    ATS(App Transport Security)というiOS9から出てきたAppleの仕様です。
    アプリの全ての通信は https でないと通信させてくれません。
    SSL証明書を入れてhttpsで通信できるようにしてみてください。

    またはATSを無効にできます。これが一番手っ取り早いです。
    http://qiita.com/tonkotsuboy_com/items/9c056b4b2b1ffb85615e
    しかし無効にするのは非推奨で、どのタイミングでAppleがこの無効の仕様を不可能にするかわかりません。

    キャンセル

0

!で強制アンラップしてる箇所 結構あるけどnilになっててアンラップできないって言われてる。

let imageData = UIImageJPEGRepresentation(self.myImageView.image!, 1)

この辺とかほんとに大丈夫ですかね? myImageView.imageがnilになってませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/02 10:52

    ありがとうございます。
    let imageData = UIImageJPEGRepresentation(self.myImageView.image!, 1)
    print("here")
    print(self.myImageView.image)
    とコードを書いて、self.myImageView.imageがあるかないかみてみたら、
    Optional(<UIImage: 0x600000092b60> size {4288, 2848} orientation 0 scale 1.000000)
    と出力され、nilではないことがわかりました。
    しかし、fatal error: unexpectedly found nil while unwrapping an Optional valueとやはりnilだと言われ、
    if(imageData==nil) { return; }
    let postString = "name=\(textField.text!)"
    の let postString = "name=\(textField.text!)" で落ちてしまいました。
    どのように検証したら、何が問題なのかわかりますか?

    キャンセル

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

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る