過去に同様の質問があったみたいでした。
swiftでアルバムからQRコード画像を読み込み、解析したい
https://teratail.com/questions/163956
How to read QR code from static image
https://stackoverflow.com/questions/35956538/how-to-read-qr-code-from-static-image
stackoverflowのコードを参考に確認してみたところSwift5.7でも動くみたいでした。
*言語のバージョンが上がってもっと良い書き方ができるのかどうかまではわかりません・・
swift
1 struct ContentView : View {
2 @ State var photoPickerItems : [ PhotosPickerItem ] = [ ]
3 var body : some View {
4 //QR画像選択
5 PhotosPicker (
6 selection : $photoPickerItems , // Bindingした[PhotosPickerItem]
7 maxSelectionCount : 1 , // 選択する写真の数(0で無制限)
8 selectionBehavior : . ordered , // 順番が関係するか
9 matching : . images , // 写真の種類を選択(nilでどれでも可に)
10 preferredItemEncoding : . current , // エンコードの種類(基本currentでいいはず)
11 photoLibrary : . shared ( ) ) { // ライブラリの選択
12 Text ( "QRコードを読み込む" )
13 . foregroundColor ( MyColor . HighlightColor )
14 }
15 . onChange ( of : photoPickerItems , perform : action ) // ***** onChange(of:perform:) modifierでphotoPickerItemsが変わったら処理が動くようにします。
16 }
17 // ***** 写真を選択してphotoPickerItemsが変わったら呼び出されるメソッドです。
18 func action ( equatable : any Equatable ) {
19 guard let items = equatable as ? [ PhotosPickerItem ] else {
20 return
21 }
22 Task {
23 // ***** photoPickerItemsは配列ですので(選択できるのは1つに限定しているとは思いますが)、配列の数だけ繰り返します。
24 for item in items {
25 // ***** PhotosPickerItemをData型に変換して、さらにUIImage型に変換します。
26 guard let data = try ? await item . loadTransferable ( type : Data . self ) ,
27 let image = UIImage ( data : data ) else {
28 continue
29 }
30 // ***** UIImageからQRコードを検出します。
31 // ***** 1つの画像から複数のQRコードが検出されるとfeatures配列の要素は複数になると思います。
32 // ***** QRコードが検出できない場合はfeatures配列は要素数が0になると思います。
33 let features = detectQRCode ( image )
34 for feature in features {
35 // ***** QRコードが正しく検出できたらmessageStringにURLが入っているはずです。
36 print ( feature . messageString ? ? "nope" ) // https://jingged.com
37 }
38 }
39 }
40 }
41 // ***** UIImageからQRコードを検出するメソッドです。
42 func detectQRCode ( _ image : UIImage ? ) - > [ CIQRCodeFeature ] {
43 guard let image = image ,
44 let ciImage = CIImage ( image : image ) else {
45 return [ ]
46 }
47 let context = CIContext ( )
48 let options1 : [ String : Any ] = [ CIDetectorAccuracy : CIDetectorAccuracyHigh ]
49 guard let qrDetector = CIDetector ( ofType : CIDetectorTypeQRCode , context : context , options : options1 ) else {
50 return [ ]
51 }
52 let options2 : [ String : Any ] = ciImage . properties . keys . contains ( ( kCGImagePropertyOrientation as String ) ) ?
53 [ CIDetectorImageOrientation : ciImage . properties [ ( kCGImagePropertyOrientation as String ) ] ? ? 1 ] :
54 [ CIDetectorImageOrientation : 1 ]
55 let features = qrDetector . features ( in : ciImage , options : options2 )
56 let qrCodeFeatures = features . compactMap ( { $ 0 as ? CIQRCodeFeature } )
57 return qrCodeFeatures
58 }
59 }
追記です。
コメントありがとうございます。
説明不足ですみません・・
SwiftUIのViewの記述からコードを記載するようにしてみました。
今回はもう少しコメントも記述してみました。
「// *****」のコメントも読んでみてください。
messageStringにurlを代入するのでしょうか?
messageStringに欲しい結果(URL)が格納されていますので、それを使って何か必要な処理を書いてみてください。
追記2です。
コメントありがとうございます。
戻り値の型をstringで指定して返そうとすると、
このエラーが、関数を呼び出す部分で発生します。
voidに変換できないとのことですが、そもそもvoid型はデータ型不明というような型ではないのでしょうか?
Voidはメソッド(関数)の戻り値がない場合ですね。
actionメソッドは onChange(of:perform:)
のperformパラメータに渡していますが、
このパラメータは @escaping (V) -> Void
の型ということになっています。
戻り値がVoidの型を要求していますので、Stringに変更したものはこの型に合わず、
エラーになっていると思います。
onChange(of:perform:) | Apple Developer Documentation
ですので、actionの中からビューのプロパティに直接設定するとか、
(戻り値で返すのではなく)
そういう感じになるのかなと思います。
その先の具体的な処理の内容をご提示いただけましたら、
もう少し具体的な回答ができるかもしれません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/05 02:12
2022/12/05 12:50
2022/12/05 14:08 編集
2022/12/05 14:36
退会済みユーザー
2022/12/06 00:59
2022/12/06 02:01