回答編集履歴

2

エラーについてのコメントを追記しました。

2022/12/05 14:29

投稿

退会済みユーザー
test CHANGED
@@ -84,3 +84,27 @@
84
84
  > messageStringにurlを代入するのでしょうか?
85
85
  messageStringに欲しい結果(URL)が格納されていますので、それを使って何か必要な処理を書いてみてください。
86
86
 
87
+ ### 追記2です。
88
+
89
+ コメントありがとうございます。
90
+
91
+ > 戻り値の型をstringで指定して返そうとすると、
92
+ > このエラーが、関数を呼び出す部分で発生します。
93
+ > voidに変換できないとのことですが、そもそもvoid型はデータ型不明というような型ではないのでしょうか?
94
+
95
+ Voidはメソッド(関数)の戻り値がない場合ですね。
96
+
97
+ actionメソッドは `onChange(of:perform:)` のperformパラメータに渡していますが、
98
+ このパラメータは `@escaping (V) -> Void` の型ということになっています。
99
+ 戻り値がVoidの型を要求していますので、Stringに変更したものはこの型に合わず、
100
+ エラーになっていると思います。
101
+
102
+ [onChange(of:perform:) | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/view/onchange(of:perform:))
103
+
104
+ ですので、actionの中からビューのプロパティに直接設定するとか、
105
+ (戻り値で返すのではなく)
106
+ そういう感じになるのかなと思います。
107
+
108
+ その先の具体的な処理の内容をご提示いただけましたら、
109
+ もう少し具体的な回答ができるかもしれません。
110
+

1

コードにViewも追記しました。コメントも追記しました。

2022/12/05 11:50

投稿

退会済みユーザー
test CHANGED
@@ -11,38 +11,76 @@
11
11
  *言語のバージョンが上がってもっと良い書き方ができるのかどうかまではわかりません・・
12
12
 
13
13
  ```swift
14
+ struct ContentView: View {
14
- func detectQRCode(_ image: UIImage?) -> [CIFeature]? {
15
+ @State var photoPickerItems: [PhotosPickerItem] = []
15
- guard let image = image,
16
+ var body: some View {
17
+ //QR画像選択
18
+ PhotosPicker(
19
+ selection: $photoPickerItems, // Bindingした[PhotosPickerItem]
20
+ maxSelectionCount: 1, // 選択する写真の数(0で無制限)
21
+ selectionBehavior: .ordered, // 順番が関係するか
22
+ matching: .images, // 写真の種類を選択(nilでどれでも可に)
23
+ preferredItemEncoding: .current, // エンコードの種類(基本currentでいいはず)
16
- let ciImage = CIImage(image: image) else {
24
+ photoLibrary: .shared()){ // ライブラリの選択
17
- return nil
25
+ Text("QRコードを読み込む")
26
+ .foregroundColor(MyColor.HighlightColor)
27
+ }
28
+ .onChange(of: photoPickerItems, perform: action) // ***** onChange(of:perform:) modifierでphotoPickerItemsが変わったら処理が動くようにします。
18
29
  }
30
+ // ***** 写真を選択してphotoPickerItemsが変わったら呼び出されるメソッドです。
19
- let context = CIContext()
31
+ func action(equatable: any Equatable) {
20
- let options1: [String : Any] = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
21
- let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options1)
22
- guard let qrDetector = qrDetector else {
32
+ guard let items = equatable as? [PhotosPickerItem] else {
23
- return nil
33
+ return
34
+ }
35
+ Task {
36
+ // ***** photoPickerItemsは配列ですので(選択できるのは1つに限定しているとは思いますが)、配列の数だけ繰り返します。
37
+ for item in items {
38
+ // ***** PhotosPickerItemをData型に変換して、さらにUIImage型に変換します。
39
+ guard let data = try? await item.loadTransferable(type: Data.self),
40
+ let image = UIImage(data: data) else {
41
+ continue
42
+ }
43
+ // ***** UIImageからQRコードを検出します。
44
+ // ***** 1つの画像から複数のQRコードが検出されるとfeatures配列の要素は複数になると思います。
45
+ // ***** QRコードが検出できない場合はfeatures配列は要素数が0になると思います。
46
+ let features = detectQRCode(image)
47
+ for feature in features {
48
+ // ***** QRコードが正しく検出できたらmessageStringにURLが入っているはずです。
49
+ print(feature.messageString ?? "nope") // https://jingged.com
50
+ }
51
+ }
52
+ }
24
53
  }
54
+ // ***** UIImageからQRコードを検出するメソッドです。
55
+ func detectQRCode(_ image: UIImage?) -> [CIQRCodeFeature] {
56
+ guard let image = image,
57
+ let ciImage = CIImage(image: image) else {
58
+ return []
59
+ }
60
+ let context = CIContext()
61
+ let options1: [String : Any] = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
62
+ guard let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options1) else {
63
+ return []
64
+ }
25
- let options2: [String : Any] = ciImage.properties.keys.contains((kCGImagePropertyOrientation as String)) ?
65
+ let options2: [String : Any] = ciImage.properties.keys.contains((kCGImagePropertyOrientation as String)) ?
26
- [CIDetectorImageOrientation: ciImage.properties[(kCGImagePropertyOrientation as String)] ?? 1] :
66
+ [CIDetectorImageOrientation: ciImage.properties[(kCGImagePropertyOrientation as String)] ?? 1] :
27
- [CIDetectorImageOrientation: 1]
67
+ [CIDetectorImageOrientation: 1]
28
- let features = qrDetector.features(in: ciImage, options: options2)
68
+ let features = qrDetector.features(in: ciImage, options: options2)
29
- return features
30
- }
31
-
32
- // 呼び出し側のイメージです。
33
- func action() {
34
- // PhotosPickerItem.loadTransferableなどを使って画像をUIImage型にしておきます。
35
- // PhotosPickerItem -> Data -> UIImageの順番で変換するイメージでしょうか?
36
- // https://developer.apple.com/documentation/photokit/photospickeritem
37
- let image: UIImage = #imageLiteral(resourceName: "qrcode")
38
- guard let features = detectQRCode(image) else {
39
- return
40
- }
41
- let qrCodeFeatures = features.compactMap({ $0 as? CIQRCodeFeature })
69
+ let qrCodeFeatures = features.compactMap({ $0 as? CIQRCodeFeature })
42
- for feature in qrCodeFeatures {
70
+ return qrCodeFeatures
43
- // QRコードが正しく検出できたらmessageStringにURLが入っているはずです。
44
- print(feature.messageString ?? "nope")
45
71
  }
46
72
  }
47
73
  ```
48
74
 
75
+ ### 追記です。
76
+
77
+ コメントありがとうございます。
78
+
79
+ 説明不足ですみません・・
80
+ SwiftUIのViewの記述からコードを記載するようにしてみました。
81
+ 今回はもう少しコメントも記述してみました。
82
+ 「// *****」のコメントも読んでみてください。
83
+
84
+ > messageStringにurlを代入するのでしょうか?
85
+ messageStringに欲しい結果(URL)が格納されていますので、それを使って何か必要な処理を書いてみてください。
86
+