I'm getting a crash reported on my call to date(from:) on my formatter:
guard let date = DateFormatter.longYearFormatter(timeZone: timeZone).date(from: dateString) else { return }
dateString here is non-optional, and looks like: "2021-11-05T14:03:00GMT-04:00"
This is the longYearFormatter:
static func longYearFormatter(timeZone: TimeZone? = .current) -> DateFormatter {
return DateFormatter(timeZone: timeZone,
format: "yyyy-MM-dd'T'HH:mm:ssZZZZ")
}
Here is the stack trace:
Crashed: com.apple.root.default-qos
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x000000000000007b
0
libicucore.A.dylib
icu::Calendar::clear() + 120
1
CoreFoundation
__cficu_ucal_clear + 24
2
CoreFoundation
__cficu_ucal_clear + 24
3
CoreFoundation
CFDateFormatterGetAbsoluteTimeFromString + 392
4
CoreFoundation
CFDateFormatterCreateDateFromString + 104
5
Foundation
getObjectValue + 268
6
Foundation
-[NSDateFormatter getObjectValue:forString:errorDescription:] + 196
7
Foundation
-[NSDateFormatter dateFromString:] + 60
Does anyone know what might be causing this issue? It doesn't happen every time this function is called and seems to be relatively rare.
I've tried running my simulator in different languages, regions, time zones, 24 vs 12hr time, etc, and I can't repro it myself.
Thanks a lot in advance!
UPDATE
Here is what the custom DateFormatter init looks like:
public extension DateFormatter {
private convenience init(timeZone: TimeZone?,
format: String) {
self.init()
self.timeZone = timeZone ?? .current
locale = Locale(identifier: "en_US_POSIX")
dateFormat = format
}
Related
I’m new to iOS (Swift) development, and I’ve been tinkering with this all week. I am trying to update only the city of the postal addresses of a contact from iOS Contacts, and leave the rest of the postal address (street, ZIP code, etc.) intact. I figured I could just get a mutable copy of the contact.postalAddress using postalAddress.mutableCopy(), and then write to mutableCopy.city = “New City”. However, when I try this I get a -[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance error. My current solution is to create a new address filled with values from the old address, but it seems there should be a better way (like copying the old address and just changing the city, like I’m trying to do). Is there something I’m missing? Thanks!
So, what I want to work:
func updateContact(contact: CNContact) -> BooleanLiteralType{
var success = false
let store = CNContactStore()
do {
let updContact = contact.mutableCopy() as! CNMutableContact
var addrArray = [CNLabeledValue<CNPostalAddress>]()
for postAddress in updContact.postalAddresses{
let curLabel = postAddress.label
var address = postAddress.mutableCopy() as! CNMutablePostalAddress
address.city = "Cityville"
let curAddrLabeledVal = CNLabeledValue<CNPostalAddress>(label:curLabel, value:address)
addrArray.append(curAddrLabeledVal)
}
updContact.postalAddresses = addrArray
let req = CNSaveRequest()
req.update(updContact)
try store.execute(req)
success = true
}
catch let err{
print(err)
}
return success
}
This results in the following exception:
2020-05-26 00:06:19.537517+0200 My App[78089:4168944] -[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance 0x600001388b80
2020-05-26 00:06:19.545537+0200 My App[78089:4168944] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CNLabeledValue mutableCopyWithZone:]: unrecognized selector sent to instance 0x600001388b80'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23e3cf0e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff50ba89b2 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23e5dc34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x00007fff23e4190c ___forwarding___ + 1436
4 CoreFoundation 0x00007fff23e43bf8 _CF_forwarding_prep_0 + 120
5 My App 0x00000001015b4898 $s12My_App13updateContact7contactSbSo9CNContactC_tF + 1048
6 My App 0x00000001015bf3f1 $s12My_App11ContentViewV4bodyQrvg7SwiftUI05TupleD0VyAE0D0PAEE7opacityyQrSdFQOyAiEE5frame5width6height9alignmentQr12CoreGraphics7CGFloatVSg_ArE9AlignmentVtFQOyAA11ProgressBarV_Qo__Qo__AE010NavigationD0VyAiEE010navigationS5Items7leading8trailingQrqd___qd_0_tAeHRd__AeHRd_0_r0_lFQOyAiEE0uS5TitleyQrAE4TextVFQOyAE4ListVys5NeverOAE7ForEachVySaySo9CNContactCGSSAE6HStackVyAE0T4LinkVyAA10ContactRowVAA13ContactDetailVGGGG_Qo__AE6ButtonVyA4_GA29_Qo_GtGyXEfU_A30_yXEfU_yycfU2_yycfU_ + 465
7 My App 0x00000001015bf8f0 $sIeg_IeyB_TR + 48
8 libdispatch.dylib 0x0000000101877f11 _dispatch_call_block_and_release + 12
9 libdispatch.dylib 0x0000000101878e8e _dispatch_client_callout + 8
10 libdispatch.dylib 0x000000010187b2d8 _dispatch_queue_override_invoke + 1022
11 libdispatch.dylib 0x000000010188a399 _dispatch_root_queue_drain + 351
12 libdispatch.dylib 0x000000010188aca6 _dispatch_worker_thread2 + 135
13 libsystem_pthread.dylib 0x00007fff51c089f7 _pthread_wqthread + 220
14 libsystem_pthread.dylib 0x00007fff51c07b77 start_wqthread + 15
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
This is the solution that works, but as you can see it’s not really what I want as it requires me to define all postalAddress attributes:
func updateContact(contact: CNContact) -> BooleanLiteralType{
var success = false
let store = CNContactStore()
do {
let updContact = contact.mutableCopy() as! CNMutableContact
var addrArray = [CNLabeledValue<CNPostalAddress>]()
for postAddress in updContact.postalAddresses{
let curLabel = postAddress.label
let address = CNMutablePostalAddress()
address.street = postAddress.value.street
address.city = "Cityville"
address.postalCode = postAddress.value.postalCode
address.state = postAddress.value.state
address.country = postAddress.value.country
address.isoCountryCode = postAddress.value.isoCountryCode
address.subAdministrativeArea = postAddress.value.subAdministrativeArea
address.subLocality = postAddress.value.subLocality
let curAddrLabeledVal = CNLabeledValue<CNPostalAddress>(label:curLabel, value:address)
addrArray.append(curAddrLabeledVal)
}
updContact.postalAddresses = addrArray
let req = CNSaveRequest()
req.update(updContact)
try store.execute(req)
success = true
}
catch let err{
print(err)
}
return success
}
Any help is much appreciated!
I am trying to use a SoundAnalyisis model that takes in audioSamples(Float32 15600) and returns a vggishFeature (MultiArray (Float32 12288) however I receive this error:
-01-22 10:45:43.404715+0000 SRTester[25654:891998] [DSPGraph] throwing DSPGraph::Exception with backtrace:
0 0x7fff2bdc0df9 DSPGraph::Graph::processMultiple(DSPGraph::GraphIOData*, DSPGraph::GraphIOData*) + 249
1 0x7fff2bd2223d SoundAnalysis::primeGraph(DSPGraph::Graph&, int) + 542
2 0x7fff2bcfbaae -[SNSoundClassifier primeGraph] + 134
3 0x7fff2bd052c2 -[SNAnalyzerHost primeAnalyzerGraph] + 88
4 0x7fff2bd0f268 -[SNAudioStreamAnalyzer configureAnalysisTreeWithFormat:] + 263
5 0x7fff2bd0f74b -[SNAudioStreamAnalyzer _analyzeAudioBuffer:atAudioFramePosition:] + 303
6 0x10af1cd48 _dispatch_client_callout + 8
7 0x10af2b9bf _dispatch_lane_barrier_sync_invoke_and_complete + 132
8 0x7fff2bd0f5d8 -[SNAudioStreamAnalyzer analyzeAudioBuffer:atAudioFramePosition:] + 121
9 0x10abb3116 $s8SRTester18homeViewControllerC16startAudioEngine33_CDAAA73F093090436FCAC2E152DEFC64LLyyFySo16AVAudioPCMBufferC_So0M4TimeCtcfU_yycfU_ + 326
10 0x10abb315d $sIeg_IeyB_TR + 45
11 0x10af1bdd4 _dispatch_call_block_and_release + 12
12 0x10af1cd48 _dispatch_client_callout + 8
13 0x10af235ef _dispatch_lane_serial_drain + 788
14 0x10af2417f _dispatch_lane_invoke + 422
15 0x10af2fa4e _dispatch_workloop_worker_thread + 719
[truncated?]
libc++abi.dylib: terminating with uncaught exception of type DSPGraph::Exception
(lldb)
The code throws the error in this line:
self.analyzer.analyze(buffer, atAudioFramePosition: time.sampleTime)
which belongs to this block of code:
/// Starts the audio engine
private func startAudioEngine() {
self.isLisitingForInferance = true
//requests to use the engine
do {
let request = try SNClassifySoundRequest(mlModel: soundClassifier.model)
try analyzer.add(request, withObserver: resultsObserver) // sets the results observator
} catch {
print("Unable to prepare request: \(error.localizedDescription)")
return
}
//starts a async task for the analyser
audioEngine.inputNode.installTap(onBus: 0, bufferSize: 16000, format: inputFormat) { buffer, time in
self.analysisQueue.async {
self.analyzer.analyze(buffer, atAudioFramePosition: time.sampleTime) //this line recives a SIGABRT
}
}
do{
try audioEngine.start()
}catch( _){
print("error in starting the Audio Engine")
}
}
Here is the class obsivation (although it does not even get triggered:
class ResultsObserver: NSObject, SNResultsObserving {
var delegate: iPhoneSpeakerRecongitionDelegate?
func request(_ request: SNRequest, didProduce result: SNResult) {
guard let result = result as? SNClassificationResult,
let classification = result.classifications.first else { return }
//print("here")
let confidence = classification.confidence * 100.0
//print(classification.)
if confidence > 60 {
delegate?.displayPredictionResult(identifier: classification.identifier, confidence: confidence)
}
}
}
Managed to get this to return a different error (which is where the model was incompatible)
To resolve this you have to manually move the model file into the app directory and then add it to xcode - it seems to be a bug in Xcode putting the model that is stored in another directory into the app package
after a successful build through xcode, the app runs in the simulator and my iPhone - when I distribute it for testing, it crashes when test users try to preform a search.
If i hardcode the URL elements - it works in both simulation mode and functions perfectly in the users test trials.
i have CrashLytics operating and it says the crash is a result of this line of code
let allContactsData = try Data(contentsOf: urlResults!)
i check in the previous VC that all the fields contain a value - and a "print" confirms the same
Company : Accountant
Suburb : Southport
State : QLD
Getting results from: http://www.myawsmurl.com.au/api/get_details.php?no=Accountant&state=QLD&suburb=Southport
var's are set at the top of the class via the following:
var toSearchFor: String = ""
var toSearchForSuburb: String = ""
var toSearchForState: String = ""
and this is the func that causes the issue:
func getResults() {
toSearchFor = searchingFor.trimmingCharacters(in: .whitespacesAndNewlines)
toSearchForSuburb = searchingSuburb.trimmingCharacters(in: .whitespacesAndNewlines)
toSearchForState = searchingState.trimmingCharacters(in: .whitespacesAndNewlines)
print("Company : \(toSearchFor)")
print("Suburb : \(toSearchForSuburb)")
print("State : \(toSearchForState)")
//toSearchFor = "Accountant"
//toSearchForSuburb = "Southport"
//toSearchForState = "QLD"
//print("Company : \(toSearchFor)")
//print("Suburb : \(toSearchForSuburb)")
//print("State : \(toSearchForState)")
let searchURL = ("http://www.myawsmurl.com.au/api/get_details.php?no=" + toSearchFor + "&state=" + toSearchForState + "&suburb=" + toSearchForSuburb)
let urlResults = URL(string:searchURL)
print("Getting results from: \(searchURL)")
do {
let allContactsData = try Data(contentsOf: urlResults!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : NSArray]
etc etc
}
catch {
}
tableView.reloadData()
}
as mentioned before, if i uncomment the hardcoded vars, it runs as excepted without issues.
any help would be appreciated as i still cant figure out why it runs in simulation mode without any issues but fails on live testing even though all fields have a value.
EDIT: (crash data)
#0. Crashed: com.apple.main-thread
0 ThisAWSMAPP 0x1000752e4 ViewController.getResults() -> () (ViewController.swift:158)
1 ThisAWSMAPP 0x100076180 specialized ViewController.viewDidAppear(Bool) -> () (ViewController.swift)
2 ThisAWSMAPP 0x100071e3c #objc ViewController.viewDidAppear(Bool) -> () (ViewController.swift)
3 UIKit 0x18cb0ddb0 -[UIViewController _setViewAppearState:isAnimating:] + 856
4 UIKit 0x18cb0e31c -[UIViewController _endAppearanceTransition:] + 228
5 UIKit 0x18cbc4d64 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 1224
6 UIKit 0x18cc93c5c __49-[UINavigationController _startCustomTransition:]_block_invoke + 232
7 UIKit 0x18cc1aa1c -[_UIViewControllerTransitionContext completeTransition:] + 116
8 UIKit 0x18cd68fac __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke.99 + 724
9 UIKit 0x18cb2e9d0 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 492
10 UIKit 0x18cb2e4f8 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
11 UIKit 0x18cb2e314 -[UIViewAnimationState animationDidStop:finished:] + 160
12 QuartzCore 0x189cdf0d4 CA::Layer::run_animation_callbacks(void*) + 260
13 libdispatch.dylib 0x18587e9a0 _dispatch_client_callout + 16
14 libdispatch.dylib 0x1858835e8 _dispatch_main_queue_callback_4CF + 996
15 CoreFoundation 0x1869750c0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
16 CoreFoundation 0x186972cdc __CFRunLoopRun + 1572
17 CoreFoundation 0x1868a2d94 CFRunLoopRunSpecific + 424
18 GraphicsServices 0x18830c074 GSEventRunModal + 100
19 UIKit 0x18cb5b130 UIApplicationMain + 208
20 ThisAWSMAPP 0x1000646d8 main (AppDelegate.swift:16)
21 libdyld.dylib 0x1858b159c start + 4
URL(string:) may return nil if the string is not a correctly formatted URL. It is not safe to force unwrap it as urlResults!, especially if you are constructing it from user input.
It safer like this:
if let url = urlResults {
let allContactsData = try Data(contentsOf:url)
// etc
} else {
// log an error for debugging
}
You should make sure the strings are URL encoded
String.trimmingCharacters only removes characters from beginning and end of the string. But your input variables may contain embedded spaces, or other illegal characters for a URL string.
Translate the input strings like this:
toSearchFor = searchingFor.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
The carsh at the given line indicates your urlResults is getting nil somehow.
Try encoding the url string before making URL object.
let toSearchFor = ""
let toSearchForSuburb = ""
let toSearchForState = ""
let searchURL = ("http://www.myawsmurl.com.au/api/get_details.php?no=" + toSearchFor + "&state=" + toSearchForState + "&suburb=" + toSearchForSuburb).addingPercentEncoding(withAllowedCharacters: . urlQueryAllowed)
if let url = searchURL, let urlResults = URL(string:url) {
print("Getting results from: \(url)")
do {
let allContactsData = try Data(contentsOf: urlResults!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : NSArray]
}
catch {
}
}
Seems like thread issue. Can you try executing your code on main thread.
DispatchQueue.main.async({
let searchURL = ("http://www.myawsmurl.com.au/api/get_details.php?no=" + toSearchFor + "&state=" + toSearchForState + "&suburb=" + toSearchForSuburb)
let urlResults = URL(string:searchURL)
print("Getting results from: \(searchURL)")
do {
let allContactsData = try Data(contentsOf: urlResults!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : NSArray]
etc etc
}
catch {}
self.tableView.reloadData()
})
When my code tries to download the series from the API, it randomly crashes with this error message:
(entity: Series; id:
0x7b181002016-04-04 14:01:33.868 Postzegel Catalogus[1816:39059]
CoreData: error: Serious application error. Exception was caught
during Core Data change processing. This is usually a bug within an
observer of NSManagedObjectContextObjectsDidChangeNotification.
-[NSCFSet addObject:]: attempt to insert nil with userInfo (null) 0 (entity: Series; id:
0x7b00c450
;
2016-04-04 14:01:33.871 Postzegel Catalogus[1816:39059] *** Terminating app due
to uncaught exception 'NSInvalidArgumentException', reason:
'-[__NSCFSet addObject:]: attempt to insert nil'
*** First throw call stack: ( 0 CoreFoundation 0x0083d494 __exceptionPreprocess + 180 1 libobjc.A.dylib
0x02551e02 objc_exception_throw + 50 2 CoreFoundation
0x0083d3bd +[NSException raise:format:] + 141 3 CoreFoundation
0x0070c959 -[__NSCFSet addObject:] + 185 4 CoreData
0x0038a010 -[NSManagedObjectContext(_NSInternalChangeProcessing)
_processPendingInsertions:withDeletions:withUpdates:] + 560 5 CoreData 0x003846da
-[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2410 6 CoreData 0x00383d56 -[NSManagedObjectContext processPendingChanges] + 54 7
CoreData 0x003ae5e4
-[NSManagedObjectContext(_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 116 8 CoreData 0x00433bec __82-[NSManagedObjectContext(_NestedContextSupport)
executeRequest:withContext:error:]_block_invoke + 412 9 CoreData
0x003a924c internalBlockToNSManagedObjectContextPerform + 76 10
libdispatch.dylib 0x03c8f9cd
_dispatch_client_callout + 14 11 libdispatch.dylib 0x03c76d90 _dispatch_barrier_sync_f_slow_invoke + 133 12
libdispatch.dylib 0x03c8f9cd
_dispatch_client_callout + 14 13 libdispatch.dylib 0x03c74f7c _dispatch_main_queue_callback_4CF + 910 14 CoreFoundation
0x007871be __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 14 15
CoreFoundation 0x00745434 __CFRunLoopRun + 2356
16 CoreFoundation 0x00744846
CFRunLoopRunSpecific + 470 17 CoreFoundation
0x0074465b CFRunLoopRunInMode + 123 18 GraphicsServices
0x07a8d664 GSEventRunModal + 192 19 GraphicsServices
0x07a8d4a1 GSEventRun + 104 20 UIKit
0x0102beb9 UIApplicationMain + 160 21 Postzegel Catalogus
0x000f63b1 main + 145 22 libdyld.dylib
0x03cb9a25 start + 1 ) (entity: Series; id: 0x7b25bc40
;
And I just don't know why? I used a private Managed Context Option so that using a . I even set the fields in my .xcdatamodeld to optional. So it shouldn't be a problem it it is nil? And it just keeps crashing randomly, not even at the same object. How can I fix this?
I included my code in the hope that might help you. I have removed my API key, so you won't be able to try it out. If you have any other comment on my code please tell me, I'm new to Core Data and Alamofire so I have the tenancy to make 'spaghetti code'.
Thanks in advance
import Foundation
import CoreData
import Alamofire
import SwiftyJSON
//CoreData Init
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext
let queue = dispatch_queue_create("com.GJ-Computers.Postzegel-Catalogus.responseJSON-Manager", DISPATCH_QUEUE_CONCURRENT)
//Colnect API
let LANG: String = NSLocale.preferredLanguages()[0].substringToIndex(NSLocale.preferredLanguages()[0].startIndex.advancedBy(2))
let DATE = NSCalendar.currentCalendar().component([.Day, .Month, .Year], fromDate: NSDate())
let API_KEY: String = "----" //Private API KEY
let CAT_STAMPS: String = ("cat/stamps/")
var BASE_URL: String{
return ("http://api.colnect.net/" + LANG + "/api/" + API_KEY + "/")
}
//Ghetto Delegate
var didGetCountires: Bool = false
var didGetYears: Bool = false
var didGetSeries: Bool = false
//MARK: - First Time setup Database
func setupDatabase(){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){
getYears() //Download Years per country from database
}
}
//get Series
func getSeries(){
//Retrieve Countries from Coredata
let countryFetchRequest = NSFetchRequest(entityName: "Countries")
var results: [Countries]?
do {
results = try managedContext.executeFetchRequest(countryFetchRequest) as? [Countries]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
let resultCount = results!.count
var completedRequestCount: Int = 0
var requestedRequests = 0
for result in results!{
let countryID = result.countryID
Alamofire.request(.GET, (BASE_URL + "series/"+CAT_STAMPS+"producer/\(countryID)")).responseJSON(queue: queue, completionHandler:{ response in
if let json = response.result.value{
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = managedContext
let rawData = JSON(json)
for data in rawData {
//Setup let
let seriesID = Int(data.1.array![0].string!)
let seriesName = data.1.array![1].string
let itemCount = Int(data.1.array![2].string!)
if seriesID != 0 && itemCount != 0 && seriesName != nil{
privateMOC.performBlock{
let series = NSEntityDescription.insertNewObjectForEntityForName("Series", inManagedObjectContext: managedContext) as! Series
series.countryID = countryID
series.seriesID = seriesID
series.seriesName = seriesName
series.itemCount = itemCount
print(completedRequestCount)
do {
try privateMOC.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}else{
print("ERROR")
}
}
}
completedRequestCount += 1
print(completedRequestCount)
})
requestedRequests += 1
if(requestedRequests == resultCount){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){
while(true){
if(completedRequestCount == resultCount){
didGetSeries = true
sleep(3)
print("DEBUG - Series Done")
break
}
}
}
}
}
}
Actually, the reason, using private MOC solved your problem is because you are performing the operation in the background thread, and when you do coredata operation in the background thread you have to ensure that
Managed object contexts are bound to the thread (queue) that they are
associated with upon initialization
Managed objects retrieved from a context are bound to the same queue
that the context is bound to
FYI not because of ("I made a private MOC, but when you make one you have to consistently add it in the code otherwise it won't work. I forgot to replace managedContext with privateMOC")
Solved it Myself. I made a private MOC, but when you make one you have to consistently add it in the code otherwise it won't work. I forgot to replace managedContext with privateMOC. My bad
let series = NSEntityDescription.insertNewObjectForEntityForName("Series", inManagedObjectContext: managedContext) as! Series
should be
let series = NSEntityDescription.insertNewObjectForEntityForName("Series", inManagedObjectContext: privateMOC) as! Series
I want to symbolicate the stack trace symbols logged using [NSThread callStackSymbols] to identify the full stack backtrace calls. But, this doesn't give symbolicated trace.
0 TestApp 0x0029616f TestApp + 1823087
1 TestApp 0x003ef18d TestApp + 3236237
2 UIKit 0x2ab7bb1f <redacted> + 438
3 UIKit 0x2ac0bea3 <redacted> + 306
4 UIKit 0x2ab7bb1f <redacted> + 438
5 CoreFoundation 0x2757546d <redacted> + 48
6 CoreFoundation 0x2756e4c3 <redacted> + 234
7 UIKit 0x2ab7bc9b <redacted> + 818
8 UIKit 0x2ae32799 <redacted> + 584
9 UIKit 0x2abdfbd9 <redacted> + 308
10 UIKit 0x2ab5bdd7 <redacted> + 458
11 CoreFoundation 0x2760fffd <redacted> + 20
12 CoreFoundation 0x2760d6bb <redacted> + 278
13 CoreFoundation 0x2760dac3 <redacted> + 914
14 CoreFoundation 0x2755b3b1 CFRunLoopRunSpecific + 476
15 CoreFoundation 0x2755b1c3 CFRunLoopRunInMode + 106
16 GraphicsServices 0x2eb88201 GSEventRunModal + 136
17 UIKit 0x2abc543d UIApplicationMain + 1440
18 TestApp 0x0031581b TestApp + 2344987
19 libdyld.dylib 0x35a6baaf <redacted> + 2
I tried this with development as well as enterprise build. Neither worked out. Is there anyway to symbolicate this? I searched lot of forums and all are asking to do this with atos command like below
atos -arch armv7 -o 'app name.app'/'app name' 0x000000000
But, I am not sure whats the memory address i have to use for the above command and how to get it.
Any help would be greatly appreciated, thanks.
There's a few pieces you're skipping here. The memory addresses in atos should reference the load address and the stack address, and you'll need the dSYM file as well.
There's actually a very good writeup on apteligent called Symbolicating an iOS Crash Report about doing this manually. I would suggest reading it thoroughly to understand how symbolication works.
Here an example of how you can get binary image information at runtime.
The output of below code looks like this for example:
YourApp 0x00000001adb1e000 - arm64e - E9B05479-3D07-390C-BD36-73EEDB2B1F75
CoreGraphics 0x00000001a92dd000 - arm64e - 2F7F6EE8-635C-332A-BAC3-EFDA4894C7E2
CoreImage 0x00000001afc00000 - arm64e - CF56BCB1-9EE3-392D-8922-C8894C9F94C7
You then use the memory address of the binary image whose frame you want to symbolicate as argument in the atos command you mentioned.
Code:
import Foundation
import MachO
public struct BinaryImagesInspector {
#if arch(x86_64) || arch(arm64)
typealias MachHeader = mach_header_64
#else
typealias MachHeader = mach_header
#endif
/// Provides binary infos that are then used with the atos command to symbolicate stack traces
/// - Parameter imageNamesToLog: an optional array of binary image names to restrict the infos to
/// - Returns: An array of strings containing info on loaded binary name, its load address, architecture
/// - Note: Example:
///
/// atos -arch arm64 -o [YOUR-DSYM-ID].dSYM/Contents/Resources/DWARF/[YOUR APP] -l 0x0000000000000000 0x0000000000000000
public static func getBinaryImagesInfo(imageNamesToLog: [String]? = nil) -> [String] {
let count = _dyld_image_count()
var stringsToLog = [String]()
for i in 0..<count {
guard let dyld = _dyld_get_image_name(i) else { continue }
let dyldStr = String(cString: dyld)
let subStrings = dyldStr.split(separator: "/")
guard let imageName = subStrings.last else { continue }
if let imageNamesToLog = imageNamesToLog {
guard imageNamesToLog.contains(String(imageName)) else { continue }
}
guard let uncastHeader = _dyld_get_image_header(i) else { continue }
let machHeader = uncastHeader.withMemoryRebound(to: MachHeader.self, capacity: MemoryLayout<MachHeader>.size) { $0 }
guard let info = NXGetArchInfoFromCpuType(machHeader.pointee.cputype, machHeader.pointee.cpusubtype) else { continue }
guard let archName = info.pointee.name else { continue }
let uuid = getBinaryImageUUID(machHeader: machHeader)
let logStr = "\(imageName) \(machHeader.debugDescription) - \(String(cString: archName)) - \(uuid ?? "uuid not found")"
stringsToLog.append(logStr)
}
return stringsToLog
}
private static func getBinaryImageUUID(machHeader: UnsafePointer<MachHeader>) -> String? {
guard var header_ptr = UnsafePointer<UInt8>.init(bitPattern: UInt(bitPattern: machHeader)) else {
return nil
}
header_ptr += MemoryLayout<MachHeader>.size
guard var command = UnsafePointer<load_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else {
return nil
}
for _ in 0..<machHeader.pointee.ncmds {
if command.pointee.cmd == LC_UUID {
guard let ucmd_ptr = UnsafePointer<uuid_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else { continue }
let ucmd = ucmd_ptr.pointee
let cuuidBytes = CFUUIDBytes(byte0: ucmd.uuid.0,
byte1: ucmd.uuid.1,
byte2: ucmd.uuid.2,
byte3: ucmd.uuid.3,
byte4: ucmd.uuid.4,
byte5: ucmd.uuid.5,
byte6: ucmd.uuid.6,
byte7: ucmd.uuid.7,
byte8: ucmd.uuid.8,
byte9: ucmd.uuid.9,
byte10: ucmd.uuid.10,
byte11: ucmd.uuid.11,
byte12: ucmd.uuid.12,
byte13: ucmd.uuid.13,
byte14: ucmd.uuid.14,
byte15: ucmd.uuid.15)
guard let cuuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, cuuidBytes) else {
return nil
}
let suuid = CFUUIDCreateString(kCFAllocatorDefault, cuuid)
let encoding = CFStringGetFastestEncoding(suuid)
guard let cstr = CFStringGetCStringPtr(suuid, encoding) else {
return nil
}
let str = String(cString: cstr)
return str
}
header_ptr += Int(command.pointee.cmdsize)
guard let newCommand = UnsafePointer<load_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else { continue }
command = newCommand
}
return nil
}
}
Further reading:
How to determine binary image architecture at runtime?
https://github.com/apple/swift/blob/master/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift
https://lowlevelbits.org/parsing-mach-o-files/
https://developer.apple.com/library/archive/technotes/tn2151/_index.html
Also available as swift package on GitHub.