また、Appleがやらかしてくれたようです。あの会社はNSNotFoundの定義値を何回間違えたら気が済むんでしょうか。これで通算4回目ぐらいです。macOS 10.12で発生し10.13.1で修正された定義値のミスをまたやったわけで、失敗がまったく生かされていない。大したものです。
今回のバグは、文字列の検索処理を行っているときに発見しました。指定文字列から対象文字列の登場位置と長さをリストで返す処理を行っていたところ、NSRangeからlocationを取得したときに、これ以上見つからない場所まで来たときにNSNotFoundを返すことを期待されるわけですが、そこに前回(macOS 10.12…10.13)と同様のおかしな値を返してきました。
この(↓)AppleScriptをmacOS 13上で実行すると、エラーになります。
追記:macOS 13.1でもエラーになります。
AppleScript名:テキストのキーワード検索(結果をNSRangeのlistで返す).scptd |
— Created 2017-08-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –http://piyocast.com/as/archives/4771 property NSString : a reference to current application’s NSString property NSMutableArray : a reference to current application’s NSMutableArray property NSLiteralSearch : a reference to current application’s NSLiteralSearch set aStr to "ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC " set aRes to searchWordRanges(aStr, "ATGC") of me as list –> {{location:0, length:4}, {location:10, length:4}, {location:20, length:4}, {location:30, length:4}, {location:40, length:4}, {location:50, length:4}, {location:60, length:4}, {location:70, length:4}} on searchWordRanges(aTargText as string, aSearchStr as string) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange set aLoc to detectedRange’s location log aLoc if (detectedRange’s location) is equal to (current application’s NSNotFound) then exit repeat hitArray’s addObject:detectedRange set aNum to (detectedRange’s location) as number set bNum to (detectedRange’s |length|) as number set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordRanges |
症状も前回とまったく同じなので、対処も前回と同じです。Appleは定期的にNSNotFoundの定義値を間違えるトンでもない会社なので(計測された事実)、NSNotFoundまわりはAppleがバグをやらかすことを前提に書いておくべきなんでしょう。
AppleScript名:テキストのキーワード検索(結果をNSRangeのlistで返す)v2.scptd |
— Created 2017-08-09 by Takaaki Naganoya — Modified 2022-12-01 by Takaaki Naganoya — 2022 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSString : a reference to current application’s NSString property NSMutableArray : a reference to current application’s NSMutableArray property NSLiteralSearch : a reference to current application’s NSLiteralSearch set aStr to "ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC " set aRes to searchWordRanges(aStr, "ATGC") of me as list –> {{location:0, length:4}, {location:10, length:4}, {location:20, length:4}, {location:30, length:4}, {location:40, length:4}, {location:50, length:4}, {location:60, length:4}, {location:70, length:4}} –> {{location:0, |length|:4}, {location:10, |length|:4}, {location:20, |length|:4}, {location:30, |length|:4}, {location:40, |length|:4}, {location:50, |length|:4}, {location:60, |length|:4}, {location:70, |length|:4}} on searchWordRanges(aTargText as string, aSearchStr as string) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange set aLoc to detectedRange’s location –macOS 13でAppleが新たに作ったバグを回避 if (aLoc > 9.999999999E+9) or (aLoc = current application’s NSNotFound) then exit repeat hitArray’s addObject:detectedRange set aNum to (detectedRange’s location) as number set bNum to (detectedRange’s |length|) as number set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordRanges |
Appleと協議した結果、そこは仕様として認識していないという話で、とくに仕様を変えていないという話で平行線をたどってしまいました。
結局、書き方を少々変えることで問題そのものを「なかったこと」にする方向で決着。納得はできませんが、macOS 10.11とか10.12の時代に書いたScriptでもあり、その実行環境は手元に残っていません(macOS 10.13は何台か存在しています。macOS 11のASのCocoa呼び出しバグの検証時に活躍)。
AppleScript名:テキストのキーワード検索(結果をNSRangeのlistで返す)v3.scptd |
— Created 2017-08-09 by Takaaki Naganoya — Modified 2022-08-29 by Takaaki Naganoya — 2023 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSString : a reference to current application’s NSString property NSLiteralSearch : a reference to current application’s NSLiteralSearch property NSMutableArray : a reference to current application’s NSMutableArray set aStr to "ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC " set aRes to searchWordRanges(aStr, "ATGC") of me as list –> {{location:0, |length|:4}, {location:10, |length|:4}, {location:20, |length|:4}, {location:30, |length|:4}, {location:40, |length|:4}, {location:50, |length|:4}, {location:60, |length|:4}, {location:70, |length|:4}} on searchWordRanges(aTargText as string, aSearchStr as string) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange set aLen to (detectedRange’s |length|) as number if aLen = 0 then exit repeat hitArray’s addObject:detectedRange set aNum to (detectedRange’s location) as number set bNum to (detectedRange’s |length|) as number set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordRanges |