2016-11-26 5 views
0

他のすべてのBAD_ACCESSは通常、迅速なタイプミスを修正したが、これは、このコードはの.ics Googleカレンダーファイルをダウンロードして、パーサ関数に渡す、ということになっているファントムEXC_BAD_ACCESS

非常に紛らわしいですこの行は

呼び出されたときにEXC_BAD_ACCESSがスローされます)物理的なiOSデバイス、loadEventIntoCalendar(のすべてのサード第四実行時に試験した場合に問題が、あるイベントオブジェクト(ここでは含まれていない)

の配列を返しますtempHold = calendarString.substring(with: tempRange)

は、event()関数のwhileループ内にあります。

この問題をさまざまな手法で解決しようとしました。 ゾンビのオブジェクトをまっすぐにしても、ログには何も印刷されません。 Instrumentsでランを分析しようとしましたが、そこには何も役立ちませんでした。私は引数で渡されたStringファイルの別のコピーを作成しようとしましたが、何も変更されませんでした。

問題がcalendarStringと何か関係があるか、少なくともそれが指している値であることは肯定的です。私はXcodeを介してメモリブロックを分析しようとしましたが、変数を見つけることができず、エラーの原因となっているメモリ位置を指していました。

は私だけシングルトン静的関数であると考えられる

イベント()(インスツルメンツでチェック)、約70メガバイトの最大を占めるRAMが全体のアプリとして、オーバーロードされないことをかなり確信しています。ここで

は2つの機能は、これは比較的すぐに完了する必要があります

func loadEventsIntoCalendar() { 
    // The link from which the calendar is downloaded 
    let url = URL (string: "https://calendar.google.com/calendar/ical/wlmacci%40gmail.com/public/basic.ics")! 


    // The process of downloading and parsing the calendar 
    let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in 
     // The following is simply a declaration and will not execute without the line 'task.resume()' 
     if let URLContent = data { // If Data has been loaded 
      // If you got to this point then you've downloaded the calendar so... 
      // Calendar File parsing starts here!!! 
      // The string that holds the contents of the calendar's events 
      var webContent:String = String(data: URLContent, encoding:String.Encoding.utf8)! 
      self.events(forCalendarFile: &webContent, inCalendar: Calendar(identifier: Calendar.Identifier.gregorian)) 
     } 
    }) 
    task.resume() 
} 

// Calendar Parser for this VC 
func events(forCalendarFile webContent:inout String, inCalendar calendar:Calendar) { 
    // The reason for this complication is, i thought copying the object might solve the issue, it did not :(
    let NSWebContent = NSString(string: webContent) 
    let calendarString = NSWebContent.copy() as! NSString 

    // An array of flags used for locating the event fields 
    // [h][0] - The flag that marks the begining of a field, [h][1] - The flag that marks the end of a field 
    let searchTitles:[[String]] = [["SUMMARY:", "TRANSP:"], ["DESCRIPTION:", "LAST-MODIFIED:"], ["DTSTART", "DTEND"], ["DTEND", "DTSTAMP"], ["LOCATION:", "SEQUENCE:"]] 

    // The range of "webContent's" content that is to be scanned 
    // Must be decreased after each event is scanned 
    var range:NSRange = NSMakeRange(0, calendarString.length - 1) 
    // Inside function that will be used to determine the 'difference' range between the begining and end flag ranges. 
    let findDifference:(NSRange, NSRange) -> NSRange = {(first:NSRange, second:NSRange) -> NSRange in 
     let location = first.location + first.length, length = second.location - location // Determine the start position and length of our new range 
     return NSMakeRange(location, length)            // Create and return the new range 
    } 
    // Inside function that will be used to move the searching range to the next event 
    // Returns an NSNotFound range (NSNotFound, 0) if there are no more events 
    let updateRange:(NSRange) -> NSRange = {(oldRange:NSRange) -> NSRange in 
     let beginingDeclaration = calendarString.range(of: "BEGIN:VEVENT", options: NSString.CompareOptions.literal, range: oldRange) 
     // If the "BEGIN:VEVENT" was not found in webContent (no more events) 
     if NSEqualRanges(beginingDeclaration, NSMakeRange(NSNotFound, 0)) { 
      return beginingDeclaration // Return an 'NSNotFound' range (Named it myself;) 
     } 
     // Calculate the index of the last character of 'beginingDeclaration' flag 
     let endOfBeginingDeclaration = beginingDeclaration.location + beginingDeclaration.length 
     // Calculate the length of the new range 
     let length = oldRange.length - endOfBeginingDeclaration + oldRange.location 
     // Calculate the starting location of the new range 
     let location = endOfBeginingDeclaration 
     // Create and return the new range 
     return NSMakeRange(location, length) 
    } 

    // A holder for the begining and end flags for each event field 
    var fieldBoundaries:[NSRange] 
    // The actual parsing of each event 
    repeat { 
     range = updateRange(range) // Move our searching range to the next event 
     if NSEqualRanges(range, NSMakeRange(NSNotFound, 0)) { // If there are no more events in the searching range 
      break;            // Then no more shall be added (break from the loop) 
     } 

     var tempHold:String! 
     // Record each field into our event database 
     for h in 0...searchTitles.count-1 { 
      fieldBoundaries = [NSRange]() // Clear the fieldBoundaries for the new search 
      fieldBoundaries.append(calendarString.range(of: searchTitles[h][0], options: NSString.CompareOptions.literal, range: range)) // Find the begining flag 
      fieldBoundaries.append(calendarString.range(of: searchTitles[h][1], options: NSString.CompareOptions.literal, range: range)) // Find the ending flag 
      let tempRange = findDifference(fieldBoundaries[0], fieldBoundaries[1]) 
      print ("Isolating event content") 
      tempHold = calendarString.substring(with: tempRange)       // Create a new string from whatever is in between the two flags. This will be the current field of the event 
      print ("Event content isolated") 
      tempHold = tempHold.trimmingCharacters(in: CharacterSet.newlines)           // Remove all /r /n and other 'new line' characters from the event field 
      tempHold = tempHold.replacingOccurrences(of: "\u{005C}", with: "", options: .literal, range: nil)   // Replace all backslashes from the event field 
     } 
    } while (true) 
} 

なので、迅速な応答が大幅に高く評価されます。

ありがとうございます!

+0

'tempHold = calendarString.substring(with:tempRange)'やブレークポイントを 'tempRange'と' calendarString'の直前に置いてみましたか? –

+0

問題は、メモリ内のいくつかのコンポーネントが実行中の途中で壊れていたため、ブレークポイントは完全にライブの変数を1つのポイントに、破損したものを次のポイントに表示することを除き、ほとんど表示されませんでした。私にエラーの原因を表示しない – sketch204

答えて

0

実は、私がやってしまったことは、完全なアルゴリズムを書き換えています。それは少し違ったやり方で動作し、実際には20行短くなり、現在ははるかに高速です。

ご注意いただきありがとうございます!助けを感謝します。

0

私が知る限り、文字列の検索方法では、結果の範囲の長さが0であるとは限りません。 2つの範囲チェックを置き換えるとどうなりますか?

if range.location == NSNotFound { ... } 

代わりの

if NSEqualRanges(range, NSMakeRange(NSNotFound, 0)) { ... } 
+0

NSNotFoundは数値であり範囲ではないので、私はその行はうまくいくとは思わないが、とにかく感謝する。 – sketch204