What is a closure #1 error in swift? - ios

I am having trouble debugging this error. I use Crashlytics on my iOS app and have been seeing this error in a few of my apps. Here is part of the stack trace:
Here is my code inside of BusStopTimesViewController.swift (I comment what is line 140 since that seems to be where the problem is happening according to the trace):
func loadBusData(_ busUrl: String) {
let urlString = busUrl
let url = URL(string: urlString)!
...
if passingTimePredicted != "" {
let nextBusDate = dateFormatter.date(from: passingTimePredicted)
// THE FOLLOWING LINE IS LINE 140
var minutesUntilBus = (nextBusDate!.timeIntervalSince1970 - Date().timeIntervalSince1970) / 60
let calendar = Calendar.current
let hour = calendar.component(.hour, from: nextBusDate!)
let minutes = calendar.component(.minute, from: nextBusDate!)
...
}
}
My initial thought is it is because nextBusDate is nil and I am trying to work with it, but I don't think that is it because the error says nothing about nextBusDate being nil (although I should probably check if it is nil before working with it). I am confused on what this error about (closure #1) is? Any thoughts would be greatly appreciated.

Related

WARNING: Unexpected type for now playing key kMRMediaRemoteNowPlayingInfoDuration

I'm seeing the following error in my console.
WARNING: Unexpected type for now playing key kMRMediaRemoteNowPlayingInfoDuration (is CFType, should be CFNumber). Removing from now playing info dictionary.
Does anyone know what I am doing wrong?
if let duration = player.currentItem?.asset.duration {
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration
}
I have faced the same problem and fixed it Find the below solution: you have forgotten to mention".seconds"
if let currentItem = player.currentItem {
let duration = currentItem.asset.duration
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration.seconds
}
Reference: https://developer.apple.com/documentation/avfoundation/media_playback_and_selection/creating_a_basic_video_player_ios_and_tvos/controlling_background_audio

First-element-marker empty-list String. Crash happens only in production

So I have been pulling my hair out over this mysterious issue (at least for me). It only happens on App Store. I tried my best to check out my BookingViewModel codes, and I am convinced that there should be no crash there, so I did some cleaning a bit, then uploaded a new build to TestFlight, and crash happened again.
Here's a screenshot of the crash logs from Fabric's Crashlytics:
and a piece of the stacktrace:
#0. Crashed: com.apple.main-thread
0 libswiftCore.dylib 0x103e70314 swift_unknownRelease + 24
1 libswiftCore.dylib 0x103e37b5c swift_arrayDestroy + 68
2 libswiftCore.dylib 0x103c308c0 (Missing)
3 libswiftCore.dylib 0x103e40f04 swift_unownedCheck + 88
4 appname 0x102940848 BookingViewModelBookingViewModelBooking first-element-marker empty-list String (BookingViewModel.swift:167)
Lastly, the code from my BookingViewModel that has the line 167 described in the crashlog (I have edited the code for this question, I removed some lines but the idea is still there, also to make the code short):
init(_ booking: Booking, withCompleteInfoCompletion completeInfo: #escaping BookingViewModelCompleteInfoCompletion) {
let createdDate = booking.createdAt ?? ""
let username = booking.username ?? ""
let firstName = booking.firstName ?? ""
let lastName = booking.lastName ?? ""
let age = booking.age ?? ""
let birthdate = booking.birthdate ?? ""
// Final values for completion
let userDetails = "\(firstName) \(lastName) \(age) / \(birthdate)".condensedWhitespace
// Booking Status and total amount
var bookingStatus: BookingStatus = .forProcessing
if let status = booking.status,
let statusId = status.id,
let newBookingStatus = BookingStatus(rawValue: statusId) {
bookingStatus = newBookingStatus
}
var totalAmount: Double = 0.00
if bookingStatus == .forPayment || bookingStatus == .paid || bookingStatus == .forConfirmation {
if let amounts = booking.amount {
for amount in amounts {
if let amountString = amount.amount,
let amountDouble = Double(amountString) {
totalAmount = totalAmount + amountDouble
}
}
}
}
self.subtotal = String(format: "%.2f", arguments: [totalAmount])
// Payment Method
var paymentType: PaymentType = .cod
if let paymentMethod = booking.paymentMethod,
let type = PaymentType(rawValue: paymentMethod) {
paymentType = type
}
// Initial Total
let initialTotal = "₱\(self.getTotalAmount(.paypal))"
completeInfo(
"₱\(self.subtotal)", // line 167
userDetails
)
}
So question is: Is there an existing idea as to how could an app crash when it's downloaded from the App Store or Testlfight, but not when in development/debug mode (running in Xcode)?
Also, is it possible to simulate the state of the project when it's on the App Store (e.g. I've read someone's answer on SO that I could change the code signing of the project to iOS Distribution)?
Thank you!
Okay, if there's someone out there being bugged by such kind of issue, putting the line that causes the weird crash in the main thread helps!
I am not sure why though, maybe I should inspect the code more. So again, I just had to put the crashing line into the main thread like so:
DispatchQueue.main.async {
self.bookingViewModel = BookingViewModel(self.booking, withCompleteInfoCompletion: {
....
})
}
And Larme's comment above helped me a lot!

Processing payments code written in Swift 2, not sure about Swift 3 equivalent

So I have some code to process payments that I'm copying from a website:
if self.expireDateTextField.text.isEmpty == false {
let expirationDate = self.expireDateTextField.text.componentsSeparatedByString("/")
let expMonth = UInt(expirationDate[0].toInt()!)
let expYear = UInt(expirationDate[1].toInt()!)
I know toInt() was removed but what be the equivalent of the code above?
The Swift 3 equivalent of toInt() is simply Int():
let expMonth = UInt(Int(expirationDate[0])!)!
let expYear = UInt(Int(expirationDate[1]!))!
In your case, I would make two refinements in the code. Firstly, you are converting two times, which is not neccesary, you may use UInt() only.
Secondly, you may consider not to implicitly unwrap, as it could easily cause a crash.
guard let expMonth = UInt(expirationDate[0]),
let expYear = UInt(expirationDate[1]) else {
print("Error in expiration casting")
return
}

Usage of String.range in Swift 3.0

let us = "http://example.com"
let range = us.rangeOfString("(?<=://)[^.]+(?=.com)", options:.RegularExpressionSearch)
if range != nil {
let found = us.substringWithRange(range!)
print("found: \(found)") // found: example
}
This code extracts substring between backslashes and dot com in Swift 2. I searched Internet and I found that rangeOfString changed to range().
But still I could not make the code work in Swift 3.0. Could you help me ?
edit : I'm using swift 3 07-25 build.
In swift 3.0 rangeOfString syntax changed like this.
let us = "http://example.com"
let range = us.range(of:"(?<=://)[^.]+(?=.com)", options:.regularExpression)
if range != nil {
let found = us.substring(with: range!)
print("found: \(found)") // found: example
}
In latest swift 3.0 using Xcode 8 Beta 6 (latest updates to SDK):
let us = "http://example.com"
let range = us.range(of: "(?<=://)[^.]+(?=.com)", options: .regularExpression)
if range != nil {
let found = us.substring(with: range!)
print("found: \(found)") // found: example
}

What does CMErrorDomain error 103. mean? (CMPedometer)

I'm struggling totally to get CMPedometer to return any step data. However Iconfigure I get Error Domain=CMErrorDomain Code=103 "The operation couldn’t be completed. (CMErrorDomain error 103.)"
I'm using swift and have broken down the queryPedometerDataFromDate query to be as simple as possible.
let pedometer = CMPedometer()
let fromDateString = "2015-01-22"
let toDateString = "2015-01-23"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "YYYY-MM-DD"
let fromDate = dateFormatter.dateFromString(fromDateString)
let toDate = dateFormatter.dateFromString(toDateString)
pedometer.queryPedometerDataFromDate(fromDate, toDate: toDate) { (data:CMPedometerData!, error:NSError!) -> Void in
if error == nil {
println(data)
} else {
println(error)
}
}
I've enabled motion detection for my app, and have no problem getting similar data out of HealthKit.
I must be missing something simple, but I can't see what it is!
Ok, so after another day of research. You have to have the CMPedometer object as a global variable for your class. If it's defined as a local variable like in the question it won't work. Simply adding let pedometer = CDPedometer() at the class level will fix this issue.

Resources