Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Hi everyone i have a question about a problem that i would like to do in swift and to see the best possible way to do that. I currently have an approach that i don't like and would be good if i can get some ideas about it.
Here it is the problem:
DispatchQ serial which is started
Then another Thread starts and waits for a completion block that returns 1 element per run
That thread will run multiple times and it will give 1 element each time until it returns all elements
The code shouldn't proceed forward and has to wait for all the elements to be collected in a array
After the array is full then the code can proceed forward.
Example with LocationManager:
Location manager starts fetching location
It output the location each time it finds a new location
At the end i have to collect all the locations i have gotten in 10 sec for example
Then proceed the work of the current thread
Example code:
var queue = DispatchQueue("q")
queue.async {
var locationCollected = Array<Location>()
// this will output multiple times
getLocation { location in
// add location to the collection
locationCollected.append(location)
}
// the current Q need to wait until all results are collected
return locationCollected
}
func getLocation() -> Location {
// this is the function that will return location
self.manager?.location(completion: { location in
// will provide location and update
completion(location)
}
}
Thank you much appreciated the help
If you want to adopt a linear flow of code approach then you can adopt the new async/await construct but that will limit your iOS versions.
In general blocking threads is best avoided as it can cause deadlocks. You should use completion handlers to get your asynchronous result rather than blocking.
For the purposes of this answer I will stick with the approach in your question.
Based on the requirements in your question, let's create a function that:
Fetches locations for a specified duration
Only fetches one location at a time
Provides the fetched location in an array
Is, itself, an asynchronous function
We need to ensure only a single location fetch is active at a time, which we can do with a DispatchSemaphore
func getLocations(for duration: TimeInterval, completion: (([Location])->Void)) {
var queue = DispatchQueue("q")
queue.async {
let semaphore = DispatchSemaphore(0)
var locationCollected = [Location]()
let startTime = Date()
while (startTime.timeIntervalSinceNow > -duration) {
getLocation { location in
locationCollected.append(location)
semaphore.signal()
}
semaphore.wait()
}
completion(result)
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have an rest Api async method, so use dispatch group:
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
Task.do { result in
defer { dispatchGroup.leave() }
//...
}
this make a crash Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
But
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
Task.do { result in
//...
dispatchGroup.leave()
}
don't crash. Why?
Point 1 is : defer is called when scope of your function ends ...
Point 2 is : dispatchGroup enter should be equal to leaves otherwise your application will crash
I've already read a lot of questions about this on stack, but is there any solution to fix this to get the missing part of the crashreport?
I understand that these crashes were caused by some reason of nil or unwrapped options or something else, but crashes from objc are much better:
My project is based on objetive-c (started a few years ago) but the new big parts are written in swift. All crashes which are coming from the objc part are well detailed but those which are coming from the swift part not.
So the question is, how will I get readable crash reports instead of EXC_BREAKPOINT 0x00000001028817ac
For such cases, I would recommend adding advanced analytics of user behavior in the app and then try to repeat the same steps as the user. This will help to find the root of such crashes. I can share the code on the foundation of which you may add the necessary functionality on the screens of your app:
import Foundation
import Crashlytics
class EventLogger {
/// Log a handled non-fatal exception
class func logException(_ exception: NSException) {
print("Catched exception: \(exception.debugDescription)")
let frames = exception.callStackSymbols.map { symbol in CLSStackFrame(symbol: symbol) }
Crashlytics.sharedInstance().recordCustomExceptionName(exception.name.rawValue, reason: exception.reason, frameArray: frames)
}
private class func log(_ string: String) {
CLSLogv(string, getVaList([]))
}
class func log(screen: String) {
log("User is located at \(screen) Screen")
}
/// Log a status of feature
class func log(feature: String, status: String) {
log("Feature \(feature) was \(status)")
}
/// Log an event
class func log(event: String) {
log("Event: \(event)")
}
}
and impement it like here:
EventLogger.log(event: "Pressed login button")
After the crash, you can see the action log exactly for this crash
Xcode 8 or 9 started displaying runtime issues. You see a purple icon at the top of the window, and a list in Issue Navigator, next to buildtime issues like compilation warnings and errors.
The runtime issues I've seen are created by the system libraries. Is there a way for my own application code to generate these?
Yes! You'll see these if you do something that a sanitizer catches, like performing certain UI operations a background thread with Thread Sanitizer enabled. Having an ambiguous layout and pausing in the view debugger is also a way to get this to occur. Either way, seeing this occur in Apple's libraries isn't a good thing…
UPDATE: I looked into how these warnings are hit, and LLDB essentially sets a breakpoint on a set of magic functions (__asan::AsanDie(), __tsan_on_report, __ubsan_on_report, __main_thread_checker_on_report) inside of a sanitizer dynamic library that are called when issues occur. If you define your own version of these functions and call them, you'll get the warning to show up. First, create the symbol somewhere in your project:
void __main_thread_checker_on_report(char *message) {
}
Then you can trigger it at will, just by putting this code anywhere in your application (you probably want to hide it behind a macro):
((void (*)(char *))dlsym(dlopen(NULL, RTLD_LAZY), "__main_thread_checker_on_report")))("This will show up as a warning")
Needless to say, this will almost certainly not play nicely with the actual sanitizer if you choose to use it. You should probably compile the above conditionally based on whether you are using a sanitizer or not.
In XCode 8.3 and earlier you can use set breakpoint into any method of UIKit class like setNeedsDisplay() like below.
Also there is library in objective-c steipete class in which #import <objc/runtime.h> is used.
But in Xcode 9 below library Xcode.app/Contenets/Developer/usr/lib/libMainThreadChecker.dylib is available, Which handle for any relevant issues potentially performed out-of-main thread at runtime.
Well, that's a hack, far from ideal, but can by useful to get runtime warnings without having game-over behavior like in assertions or fatal errors:
func runtimeWarning(_ message: String, file: String = #file, line: Int = #line) {
#if DEBUG
DispatchQueue.global(qos: .userInteractive).async {
// If you got here, please check console for more info
_ = UIApplication.shared.windows
print("Runtime warning: \(message): file \(file.fileName), line \(line)")
}
#endif
}
fileprivate extension String {
var fileName: String { URL(fileURLWithPath: self).lastPathComponent }
}
Unfortunately this leads to quite a big print to console from Main Thread Checker, also does not show on correct line, but at least you have all info needed in console (including line of code you should check).
Usage and result is very similar to assertionFailure or fatalError:
runtimeWarning("Hi, I'm purple")
leads to message in console:
Runtime warning: Hi, I'm purple: file MyFile.swift, line 10
and this, so you won't miss it:
Just wanted to add a Swift implementation of a runtimeWarning method, for anyone curious:
func runtimeWarning(_ message: String) {
// Load the dynamic library.
guard let handle = dlopen(nil, RTLD_NOW) else {
fatalError("Couldn't find dynamic library for runtime warning.")
}
// Get the "__main_thread_checker_on_report" symbol from the handle.
guard let sym = dlsym(handle, "__main_thread_checker_on_report") else {
fatalError("Couldn't find function for runtime warning reporting.")
}
// Cast the symbol to a callable Swift function type.
typealias ReporterFunction = #convention(c) (UnsafePointer<Int8>) -> Void
let reporter = unsafeBitCast(sym, to: ReporterFunction.self)
// Convert the message to a pointer
message.withCString { messagePointer in
// Call the reporter with the acquired messagePointer
reporter(messagePointer)
}
}
CocoaLumberjack framework can be used to capture Run times console logs as well as App's Background wakeup logs.
https://github.com/CocoaLumberjack/CocoaLumberjack
https://github.com/phonegap/phonegap-plugin-push/issues/1988
This way you can capture purple warnings displayed in Xcode9 like below in a file that is maintained inside App Container:-
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication registerUserNotificationSettings:]
PID: 2897, TID: 1262426, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21
It depends on you if you are doing any UI related stuff on other then main thread so system will generate for you else you can not manually generate it.
All UI manipulations should be done in the Main Thread.
If you are not doing this so, in XCode 9 have feature called Main thread checker.
For more info, you can visit below url: https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
It is basically used to checks whether any UIKit related stuff is happening on a main thread or not ?, If failed to do so, it will produce issues at Runtime. So wrap your code in Main Thread block like below to avoid glitches and runtime warnings.
You can Enable - Disable using this steps Edit Scheme... -> (Select your scheme) -> Diagnostics -> Disable 'Main thread checker'
Swift Composable Architecture folks dug into this and found a solution
You should read about it here
And you can get the code here
which you can then use as
runtimeWarning("This is neat")
full code because SO likes code rather than references:
#if DEBUG
import os
import XCTestDynamicOverlay
// NB: Xcode runtime warnings offer a much better experience than traditional assertions and
// breakpoints, but Apple provides no means of creating custom runtime warnings ourselves.
// To work around this, we hook into SwiftUI's runtime issue delivery mechanism, instead.
//
// Feedback filed: https://gist.github.com/stephencelis/a8d06383ed6ccde3e5ef5d1b3ad52bbc
private let rw = (
dso: { () -> UnsafeMutableRawPointer in
let count = _dyld_image_count()
for i in 0..<count {
if let name = _dyld_get_image_name(i) {
let swiftString = String(cString: name)
if swiftString.hasSuffix("/SwiftUI") {
if let header = _dyld_get_image_header(i) {
return UnsafeMutableRawPointer(mutating: UnsafeRawPointer(header))
}
}
}
}
return UnsafeMutableRawPointer(mutating: #dsohandle)
}(),
log: OSLog(subsystem: "com.apple.runtime-issues", category: "ComposableArchitecture")
)
#endif
#_transparent
#inline(__always)
func runtimeWarning(
_ message: #autoclosure () -> StaticString,
_ args: #autoclosure () -> [CVarArg] = []
) {
#if DEBUG
let message = message()
unsafeBitCast(
os_log as (OSLogType, UnsafeRawPointer, OSLog, StaticString, CVarArg...) -> Void,
to: ((OSLogType, UnsafeRawPointer, OSLog, StaticString, [CVarArg]) -> Void).self
)(.fault, rw.dso, rw.log, message, args())
XCTFail(String(format: "\(message)", arguments: args()))
#endif
}
code is MIT licenced
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm coding an app for my Kids. I have background in Java but havn't professionally coded in a decade. I don't thoroughly understand how the following line works but it worked in Swift 1.2:
leaderboardRequest.loadScoresWithCompletionHandler({ (scores:[AnyObject]!, error:NSError!) -> Void in
if (error != nil)
{
I need help translating this into working Swift 2.0 code. Could someone please post a translation of working Swift 2.0 code for the following method:
func getHighscores(leaderboardID: String) {
let leaderboardRequest = GKLeaderboard() as GKLeaderboard!
leaderboardRequest.identifier = leaderboardID
if leaderboardRequest != nil
{
leaderboardRequest.loadScoresWithCompletionHandler({ (scores:[AnyObject]!, error:NSError!) -> Void in
if (error != nil)
{
//println("error in alltimeHighscoreForLevel")
print(error.description)
self.updateLocalHighscore()
}
else
{
if(leaderboardRequest != nil){
if(leaderboardRequest.scores != nil ) {
if(leaderboardRequest.scores!.count > 0){
self.updateHighestForLevel(leaderboardRequest)
}
}
}
}
})
}
}
I think this will work for you:
leaderboardRequest.loadScoresWithCompletionHandler({ (scores, error) -> Void in
if let error = error {
// from here on your code should work
I think the definition of loadScoresWithCompletionHandler changed from the old code.
Two common ways to solve this:
Comment out the line / method which causes the error and start to retype it. The code completion will reveal the proper signature of the method. Then copy and paste the relevant code from the old line / method to the new one and resolve potential errors / warnings.
Press ⇧⌘0 and type (or copy&paste) the beginning of the method for example loadScoresWithCompletionHandler into the search field. This will take you to the documentation and you can see the whole declaration including the discussion.