set variable in SFSpeechRecognizer.requestAuthorization - swiftui

I'm trying to check whether the user has accepted the speech recognition or not. But for some reason the status is .authorized but the according variable won't be changed. What am I missing here? It's not about to display the message to the user, but just for some error handling use cases.
class ViewModel: ObservableObject {
#Published var requestAuth: Bool = false
init() {
SFSpeechRecognizer.requestAuthorization { (authState) in
DispatchQueue.main.async {
if authState == .authorized {
print("is authorized") // <---- is printed!
self.requestAuth = true
} else {
self.requestAuth = false
}
}
}
if self.requestAuth { // <--- will not be executed - why?
// do something...
}
}

The code inside the requestAuthorization braces ({}) is what's called a callback function. Often times, callback functions don't get executed immediately. In fact, the documentation for that function states:
This method executes asynchronously, returning shortly after you call it
That means that the code that follows will not happen immediately. Similarly, you're using DispatchQueue.main.async inside that callback function, which also acts the same way. The code in the braces will not be called right away, so you can't base anything later in your structure on it having happened.
The solution to this is to call any functions that you need that are based on the authorization status from inside those closures -- like where you have print("is authorized"):
init() {
SFSpeechRecognizer.requestAuthorization { (authState) in
DispatchQueue.main.async {
if authState == .authorized {
print("is authorized") // <---- is printed!
self.requestAuth = true
// do other things based on authorization status
} else {
self.requestAuth = false
}
}
}
//can't rely on having an updated value for self.requestAuth here
}

Related

Update a View after an in app purchase was done

In the meantime a try to implement in app purchases in my app that is in the AppStore.
So I done this with Glassfy and everything works fine.
final class IAPManager {
static let shared = IAPManager()
private init() {}
enum Product: String {
case comfirstmember
var sku: String {
"numberOne"
}
}
#AppStorage("boughtFirst") var boughtFirst = false
func configure() {
Glassfy.initialize(apiKey: "31876r5654fgz4f95f0e6e6bh5d")
}
func getProduct(completion: #escaping (Glassfy.Sku) -> Void) {
Glassfy.sku(id: "numberOne") { sku, error in
guard let sku = sku, error == nil else {
return
}
completion(sku)
}
}
func purchase(sku: Glassfy.Sku) {
Glassfy.purchase(sku: sku) { transaction, error in
guard let t = transaction, error == nil else {
return
}
if t.permissions["numberOne"]?.isValid == true {
NotificationCenter.default.post(
name: Notification.Name("numberOne"),
object: nil
)
self.boughtFirst = true
}
}
}
func getPermissions() {
Glassfy.permissions { permissions, error in
guard let permissions = permissions, error == nil else {
return
}
if permissions["numberOne"]?.isValid == true {
NotificationCenter.default.post(
name: Notification.Name("numberOne"),
object: nil
)
self.boughtFirst = true
}
}
}
func restorePurchases() {
Glassfy.restorePurchases { permissions, error in
guard let permissions = permissions, error == nil else {
return
}
if permissions["numberOne"]?.isValid == true {
NotificationCenter.default.post(
name: Notification.Name("numberOne"),
object: nil
)
self.boughtFirst = true
}
}
}
}
But now I need to update a View after the purchase was successfully done buy the user to display the Content that he purchased.
NavigationView {
VStack {
if boughtFirst == false {
BuyExtraContent()
}
if boughtFirst == true {
AllView()
}
}
}
I want do this as easy as possible just with AppStorage.
But if I place the Boolean in the func purchase to switch from false to true nothings changes.
So my question is how I can update a view after a successful purchase.
P.S. I´m a bit lost in SwiftUI so please explain it not to complex :)
use a state variable for this .
you used boughtFirst as a bool variable. make sure it's an observable .
try to call with observable object and when your variable will change the view will automatically notify and update by itself.
I am not sure you followed this strategy or not.

Cocoa Binding (Enabled) broken after updating to Swift4

I am trying to update my codes from Swift3.3 to Swift4.1 but encountering KVC error.
Swift4CocoaBindings[4639:2311856] [General] [<Swift4CocoaBindings.AppDelegate 0x604000000270> addObserver:<NSKeyValueObservance 0x60c000045e50> forKeyPath:#"dbCom.dbFileExists" options:256 context:0x0] was sent to an object that is not KVC-compliant for the "dbCom" property.
What I'm doing is disabling menu items depending on properties' value in my singleton class (DBCom.swift), which is inherited from NSObject.
So I created blank projects, one with Swift3.3 and the other with Swift4.1, both with same DBCom.swift, to see if this problem reproduced. And found it reproduced.
In AppDelegate.swift, I included the singleton as follows.
let dbCom = DBCom.shared
Then,
Bindings of menu items are made to Enabled with self.dbCom.dbFileExists in the InterfaceBuilder.
This was working with Swift3.3 but once it is switched to Swift4.1, the app got the error at the startup.
dbFileExists' implementation in the DBCom.swift is as follows. Just checking the file is existed or not.
var dbFileExists: Bool {
get {
if let dbfp = dbFullPath {
if FileManager.default.fileExists(atPath: dbfp.path) {
return true
} else {
return false
}
} else {
return false
}
}
}
If anyone can suggest the solution to this problem, it'd be very much appreciated.
Regards,
Cocoa Binding depends on the dynamic features of Objective-C, such as KVC/KVO.
So, all the properties included in the Cocoa Binding reference needs to be Objective-C compatible.
Try adding #obc explicitly:
#objc let dbCom = DBCom.shared
and:
#objc dynamic var dbFileExists: Bool {
get {
if let dbfp = dbFullPath {
if FileManager.default.fileExists(atPath: dbfp.path) {
return true
} else {
return false
}
} else {
return false
}
}
}
Since Swift 4, automatic annotation of #objc happens in very limited conditions and you may need to explicitly annotate each properties or methods.

How to signal the caller about the state of a promise

I have Ember code where the backend API calls are abstracted into a
separate service. This service uses ember-ajax library for making
backend calls.
This service sets up the common headers, handles the
timeout errors, and 4xx/5xx errors. And anything else like 422
(validation errors) are left to be handled by the calling code.
-
getCustomerProfile (authenticationToken) {
const backendService = this.get('callBackendService');
return backendService.callEndpoint(GET_METHOD,
getCustomerProfileAPI.url,
{'X-Auth-Token': authenticationToken}).then((customerProfileData) => {
if (!backendService.get('didAnybodyWin') && customerProfileData) {
backendService.set('didAnybodyWin', true);
return customerProfileData.profiles[0];
}
}).catch((error) => {
if (isInvalidError(error)) {
if (!backendService.get('didAnybodyWin')) {
backendService.set('didAnybodyWin', true);
backendService.transitionToErrorPage();
return;
}
}
});
}
and the call-backend-service looks like this
callEndpoint (httpVerb, endPoint, headersParameter, data = {},
timeoutInMillisecs = backendCallTimeoutInMilliseconds) {
const headersConst = {
'Content-Type': 'application/vnd.api+json',
'Accept': 'application/vnd.api+json',
'Brand': 'abc'
};
var headers = Ember.assign(headersParameter, headersConst);
var promiseFunctionWrapper;
this.set('didAnybodyWin', false);
if (httpVerb.toUpperCase() === GET_METHOD) {
Ember.Logger.warn('hit GET Method');
promiseFunctionWrapper = () => {
return this.get('ajax').request(endPoint, {headers});
};
} else if (httpVerb.toUpperCase() === POST_METHOD) {
Ember.Logger.warn('hit POST Method');
promiseFunctionWrapper = () => {
return this.get('ajax').post(endPoint, {data: data, headers: headers});
};
}
return RSVP.Promise.race([promiseFunctionWrapper(), this.delay(timeoutInMillisecs).then(() => {
if (!this.get('didAnybodyWin')) {
this.set('didAnybodyWin', true);
Ember.Logger.error('timeout of %s happened when calling the endpoint %s', backendCallTimeoutInMilliseconds, endPoint);
this.transitionToErrorPage();
return;
}
})]).catch((error) => {
if (!this.get('didAnybodyWin')) {
if (isTimeoutError(error)) {
this.set('didAnybodyWin', true);
Ember.Logger.warn('callBackEndService: isTimeoutError(error) condition is true');
this.transitionToErrorPage();
return;
} else if (isAjaxError(error) && !isInvalidError(error)) { //handles all errors except http 422 (inValid request)
this.set('didAnybodyWin', true);
Ember.Logger.warn('callBackEndService: isAjaxError(error) && !isInvalidError(error) [[ non timeout error]] condition is true');
this.transitionToErrorPage();
return;
} else {
throw error; // to be caught by the caller
}
}
});
},
The callEndpoint does a RSVP.Promise.race call to make sure the called backend API comes back before a timeout happens. It runs two promises and whichever resolves first is the one that wins. didAnybodyWin is the flag that guards both the promises from getting executed.
Up to this part is all fine.
But this didAnybodyWin becomes the shared state of this call-backend-service because it has to convey back to the caller whether it ran the default set of then or catch blocks or does it expect the caller to run its then/catch blocks.
The problem is when model() hook is run, I am doing
RSVP.all {
backendAPICall1(),
backendAPICall2(),
backendAPICAll3()
}
This RSVP.all is going to execute all 3 calls one after another, so they will hit the call-backend-service in an interleaved fashion and hence run the risk of stepping over each other (when it comes to the didAnybodyWin shared state).
How can this situation be avoided ?
Is there any other better way for the callee to signal to the caller whether or not its supposed to do something with the returned promise.

What is the Swift equivalent to Objective-C's "#synchronized"?

I've searched the Swift book, but can't find the Swift version of #synchronized. How do I do mutual exclusion in Swift?
You can use GCD. It is a little more verbose than #synchronized, but works as a replacement:
let serialQueue = DispatchQueue(label: "com.test.mySerialQueue")
serialQueue.sync {
// code
}
I was looking for this myself and came to the conclusion there's no native construct inside of swift for this yet.
I did make up this small helper function based on some of the code I've seen from Matt Bridges and others.
func synced(_ lock: Any, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
Usage is pretty straight forward
synced(self) {
println("This is a synchronized closure")
}
There is one problem I've found with this. Passing in an array as the lock argument seems to cause a very obtuse compiler error at this point. Otherwise though it seems to work as desired.
Bitcast requires both operands to be pointer or neither
%26 = bitcast i64 %25 to %objc_object*, !dbg !378
LLVM ERROR: Broken function found, compilation aborted!
I like and use many of the answers here, so I'd choose whichever works best for you. That said, the method I prefer when I need something like objective-c's #synchronized uses the defer statement introduced in swift 2.
{
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
//
// code of critical section goes here
//
} // <-- lock released when this block is exited
The nice thing about this method, is that your critical section can exit the containing block in any fashion desired (e.g., return, break, continue, throw), and "the statements within the defer statement are executed no matter how program control is transferred."1
You can sandwich statements between objc_sync_enter(obj: AnyObject?) and objc_sync_exit(obj: AnyObject?). The #synchronized keyword is using those methods under the covers. i.e.
objc_sync_enter(self)
... synchronized code ...
objc_sync_exit(self)
Analog of the #synchronized directive from Objective-C can have an arbitrary return type and nice rethrows behaviour in Swift.
// Swift 3
func synchronized<T>(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
The use of the defer statement lets directly return a value without introducing a temporary variable.
In Swift 2 add the #noescape attribute to the closure to allow more optimisations:
// Swift 2
func synchronized<T>(lock: AnyObject, #noescape _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
Based on the answers from GNewc [1] (where I like arbitrary return type) and Tod Cunningham [2] (where I like defer).
SWIFT 4
In Swift 4 you can use GCDs dispatch queues to lock resources.
class MyObject {
private var internalState: Int = 0
private let internalQueue: DispatchQueue = DispatchQueue(label:"LockingQueue") // Serial by default
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newState) {
internalQueue.sync { internalState = newState }
}
}
}
In modern Swift 5, with return capability:
/**
Makes sure no other thread reenters the closure before the one running has not returned
*/
#discardableResult
public func synchronized<T>(_ lock: AnyObject, closure:() -> T) -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return closure()
}
Use it like this, to take advantage the return value capability:
let returnedValue = synchronized(self) {
// Your code here
return yourCode()
}
Or like that otherwise:
synchronized(self) {
// Your code here
yourCode()
}
To add return functionalty, you could do this:
func synchronize<T>(lockObj: AnyObject!, closure: ()->T) -> T
{
objc_sync_enter(lockObj)
var retVal: T = closure()
objc_sync_exit(lockObj)
return retVal
}
Subsequently, you can call it using:
func importantMethod(...) -> Bool {
return synchronize(self) {
if(feelLikeReturningTrue) { return true }
// do other things
if(feelLikeReturningTrueNow) { return true }
// more things
return whatIFeelLike ? true : false
}
}
Using Bryan McLemore answer, I extended it to support objects that throw in a safe manor with the Swift 2.0 defer ability.
func synchronized( lock:AnyObject, block:() throws -> Void ) rethrows
{
objc_sync_enter(lock)
defer {
objc_sync_exit(lock)
}
try block()
}
In the "Understanding Crashes and Crash Logs" session 414 of the 2018 WWDC they show the following way using DispatchQueues with sync.
In swift 4 should be something like the following:
class ImageCache {
private let queue = DispatchQueue(label: "sync queue")
private var storage: [String: UIImage] = [:]
public subscript(key: String) -> UIImage? {
get {
return queue.sync {
return storage[key]
}
}
set {
queue.sync {
storage[key] = newValue
}
}
}
}
Anyway you can also make reads faster using concurrent queues with barriers. Sync and async reads are performed concurrently and writing a new value waits for previous operations to finish.
class ImageCache {
private let queue = DispatchQueue(label: "with barriers", attributes: .concurrent)
private var storage: [String: UIImage] = [:]
func get(_ key: String) -> UIImage? {
return queue.sync { [weak self] in
guard let self = self else { return nil }
return self.storage[key]
}
}
func set(_ image: UIImage, for key: String) {
queue.async(flags: .barrier) { [weak self] in
guard let self = self else { return }
self.storage[key] = image
}
}
}
Try: NSRecursiveLock
A lock that may be acquired multiple times by the same thread without
causing a deadlock.
let lock = NSRecursiveLock()
func f() {
lock.lock()
//Your Code
lock.unlock()
}
func f2() {
lock.lock()
defer {
lock.unlock()
}
//Your Code
}
The Objective-C synchronization feature supports recursive and
reentrant code. A thread can use a single semaphore several times in a
recursive manner; other threads are blocked from using it until the
thread releases all the locks obtained with it; that is, every
#synchronized() block is exited normally or through an exception.
Source
Swift 3
This code has the re-entry ability and can work with Asynchronous function calls. In this code, after someAsyncFunc() is called, another function closure on the serial queue will process but be blocked by semaphore.wait() until signal() is called. internalQueue.sync shouldn't be used as it will block the main thread if I'm not mistaken.
let internalQueue = DispatchQueue(label: "serialQueue")
let semaphore = DispatchSemaphore(value: 1)
internalQueue.async {
self.semaphore.wait()
// Critical section
someAsyncFunc() {
// Do some work here
self.semaphore.signal()
}
}
objc_sync_enter/objc_sync_exit isn't a good idea without error handling.
Use NSLock in Swift4:
let lock = NSLock()
lock.lock()
if isRunning == true {
print("Service IS running ==> please wait")
return
} else {
print("Service not running")
}
isRunning = true
lock.unlock()
Warning
The NSLock class uses POSIX threads to implement its locking behavior. When sending an unlock message to an NSLock object, you must be sure that message is sent from the same thread that sent the initial lock message. Unlocking a lock from a different thread can result in undefined behavior.
With Swift's property wrappers, this is what I'm using now:
#propertyWrapper public struct NCCSerialized<Wrapped> {
private let queue = DispatchQueue(label: "com.nuclearcyborg.NCCSerialized_\(UUID().uuidString)")
private var _wrappedValue: Wrapped
public var wrappedValue: Wrapped {
get { queue.sync { _wrappedValue } }
set { queue.sync { _wrappedValue = newValue } }
}
public init(wrappedValue: Wrapped) {
self._wrappedValue = wrappedValue
}
}
Then you can just do:
#NCCSerialized var foo: Int = 10
or
#NCCSerialized var myData: [SomeStruct] = []
Then access the variable as you normally would.
With the advent of Swift concurrency, we would use actors.
You can use tasks to break up your program into isolated, concurrent
pieces. Tasks are isolated from each other, which is what makes it
safe for them to run at the same time, but sometimes you need to share
some information between tasks. Actors let you safely share
information between concurrent code.
Like classes, actors are reference types, so the comparison of value
types and reference types in Classes Are Reference Types applies to
actors as well as classes. Unlike classes, actors allow only one task
to access their mutable state at a time, which makes it safe for code
in multiple tasks to interact with the same instance of an actor. For
example, here’s an actor that records temperatures:
actor TemperatureLogger {
let label: String
var measurements: [Int]
private(set) var max: Int
init(label: String, measurement: Int) {
self.label = label
self.measurements = [measurement]
self.max = measurement
}
}
You introduce an actor with the actor keyword, followed by its definition in a pair of braces. The TemperatureLogger actor has properties that other code outside the actor can access, and restricts the max property so only code inside the actor can update the maximum value.
For more information, see WWDC video Protect mutable state with Swift actors.
For the sake of completeness, the historical alternatives include:
GCD serial queue: This is a simple pre-concurrency approach to ensure that one one thread at a time will interact with the shared resource.
Reader-writer pattern with concurrent GCD queue: In reader-writer patterns, one uses a concurrent dispatch queue to perform synchronous, but concurrent, reads (but concurrent with other reads only, not writes) but perform writes asynchronously with a barrier (forcing writes to not be performed concurrently with anything else on that queue). This can offer a performance improvement over a simple GCD serial solution, but in practice, the advantage is modest and comes at the cost of additional complexity (e.g., you have to be careful about thread-explosion scenarios). IMHO, I tend to avoid this pattern, either sticking with the simplicity of the serial queue pattern, or, when the performance difference is critical, using a completely different pattern.
Locks: In my Swift tests, lock-based synchronization tends to be substantially faster than either of the GCD approaches. Locks come in a few flavors:
NSLock is a nice, relatively efficient lock mechanism.
In those cases where performance is of paramount concern, I use “unfair locks”, but you must be careful when using them from Swift (see https://stackoverflow.com/a/66525671/1271826).
For the sake of completeness, there is also the recursive lock. IMHO, I would favor simple NSLock over NSRecursiveLock. Recursive locks are subject to abuse and often indicate code smell.
You might see references to “spin locks”. Many years ago, they used to be employed where performance was of paramount concern, but they are now deprecated in favor of unfair locks.
Technically, one can use semaphores for synchronization, but it tends to be the slowest of all the alternatives.
I outline a few my benchmark results here.
In short, nowadays I use actors for contemporary codebases, GCD serial queues for simple scenarios non-async-await code, and locks in those rare cases where performance is essential.
And, needless to say, we often try to reduce the number of synchronizations altogether. If we can, we often use value types, where each thread gets its own copy. And where synchronization cannot be avoided, we try to minimize the number of those synchronizations where possible.
Figure I'll post my Swift 5 implementation, built off of the prior answers. Thanks guys! I found it helpful to have one that returns a value too, so I have two methods.
Here is a simple class to make first:
import Foundation
class Sync {
public class func synced(_ lock: Any, closure: () -> ()) {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
closure()
}
public class func syncedReturn(_ lock: Any, closure: () -> (Any?)) -> Any? {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return closure()
}
}
Then use it like so if needing a return value:
return Sync.syncedReturn(self, closure: {
// some code here
return "hello world"
})
Or:
Sync.synced(self, closure: {
// do some work synchronously
})
You can create propertyWrapper Synchronised
Here example with NSLock underhood. You can use for synchronisation whatever you want GCD, posix_locks e.t.c
#propertyWrapper public struct Synchronised<T> {
private let lock = NSLock()
private var _wrappedValue: T
public var wrappedValue: T {
get {
lock.lock()
defer {
lock.unlock()
}
return _wrappedValue
}
set {
lock.lock()
defer {
lock.unlock()
}
_wrappedValue = newValue
}
}
public init(wrappedValue: T) {
self._wrappedValue = wrappedValue
}
}
#Synchronised var example: String = "testing"
based on #drewster answer
In conclusion, Here give more common way that include return value or void, and throw
import Foundation
extension NSObject {
func synchronized<T>(lockObj: AnyObject!, closure: () throws -> T) rethrows -> T
{
objc_sync_enter(lockObj)
defer {
objc_sync_exit(lockObj)
}
return try closure()
}
}
Details
Xcode 8.3.1, Swift 3.1
Task
Read write value from different threads (async).
Code
class AsyncObject<T>:CustomStringConvertible {
private var _value: T
public private(set) var dispatchQueueName: String
let dispatchQueue: DispatchQueue
init (value: T, dispatchQueueName: String) {
_value = value
self.dispatchQueueName = dispatchQueueName
dispatchQueue = DispatchQueue(label: dispatchQueueName)
}
func setValue(with closure: #escaping (_ currentValue: T)->(T) ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
_self._value = closure(_self._value)
}
}
}
func getValue(with closure: #escaping (_ currentValue: T)->() ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
closure(_self._value)
}
}
}
var value: T {
get {
return dispatchQueue.sync { _value }
}
set (newValue) {
dispatchQueue.sync { _value = newValue }
}
}
var description: String {
return "\(_value)"
}
}
Usage
print("Single read/write action")
// Use it when when you need to make single action
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch0")
obj.value = 100
let x = obj.value
print(x)
print("Write action in block")
// Use it when when you need to make many action
obj.setValue{ (current) -> (Int) in
let newValue = current*2
print("previous: \(current), new: \(newValue)")
return newValue
}
Full Sample
extension DispatchGroup
extension DispatchGroup {
class func loop(repeatNumber: Int, action: #escaping (_ index: Int)->(), completion: #escaping ()->()) {
let group = DispatchGroup()
for index in 0...repeatNumber {
group.enter()
DispatchQueue.global(qos: .utility).async {
action(index)
group.leave()
}
}
group.notify(queue: DispatchQueue.global(qos: .userInitiated)) {
completion()
}
}
}
class ViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//sample1()
sample2()
}
func sample1() {
print("=================================================\nsample with variable")
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch1")
DispatchGroup.loop(repeatNumber: 5, action: { index in
obj.value = index
}) {
print("\(obj.value)")
}
}
func sample2() {
print("\n=================================================\nsample with array")
let arr = AsyncObject<[Int]>(value: [], dispatchQueueName: "Dispatch2")
DispatchGroup.loop(repeatNumber: 15, action: { index in
arr.setValue{ (current) -> ([Int]) in
var array = current
array.append(index*index)
print("index: \(index), value \(array[array.count-1])")
return array
}
}) {
print("\(arr.value)")
}
}
}
What about
final class SpinLock {
private let lock = NSRecursiveLock()
func sync<T>(action: () -> T) -> T {
lock.lock()
defer { lock.unlock() }
return action()
}
}
Why make it difficult and hassle with locks?
Use Dispatch Barriers.
A dispatch barrier creates a synchronization point within a concurrent queue.
While it’s running, no other block on the queue is allowed to run, even if it’s concurrent and other cores are available.
If that sounds like an exclusive (write) lock, it is.
Non-barrier blocks can be thought of as shared (read) locks.
As long as all access to the resource is performed through the queue, barriers provide very cheap synchronization.
dispatch_barrier_async is the better way, while not blocking current thread.
dispatch_barrier_async(accessQueue, {
dictionary[object.ID] = object
})
Based on ɲeuroburɳ, test an sub-class case
class Foo: NSObject {
func test() {
print("1")
objc_sync_enter(self)
defer {
objc_sync_exit(self)
print("3")
}
print("2")
}
}
class Foo2: Foo {
override func test() {
super.test()
print("11")
objc_sync_enter(self)
defer {
print("33")
objc_sync_exit(self)
}
print("22")
}
}
let test = Foo2()
test.test()
Output:
1
2
3
11
22
33
Another method is to create a superclass and then inherit it. This way you can use GCD more directly
class Lockable {
let lockableQ:dispatch_queue_t
init() {
lockableQ = dispatch_queue_create("com.blah.blah.\(self.dynamicType)", DISPATCH_QUEUE_SERIAL)
}
func lock(closure: () -> ()) {
dispatch_sync(lockableQ, closure)
}
}
class Foo: Lockable {
func boo() {
lock {
....... do something
}
}

if control does not work using check box

I cannot manage to handle the 'check-box handler', a problem, that I have traced back to happen obviously within the if-control function.
If you try the following modified code, you see, that the Boolean-variable "e.parameter.myCheckBox" yields the correct result, the if-branching-off based on this variable, however, does not work. Does anyone see the mistake here?
Thank you very much
Martin
function ifTest(e) {
var app = UiApp.createApplication().setTitle('ifTest');
var panel = app.createVerticalPanel();
var grid = app.createGrid(3, 3);
var myCheckBox = app.createCheckBox().setName('myCheckBox').setId('myCheckBox');
var button = app.createButton('submit').setId("submit").setWidth("280").setHeight("35");
grid.setWidget(1, 0, app.createLabel('Check for True').setStyleAttribute("font-size", "110%"));
grid.setWidget(1, 1, myCheckBox);
grid.setWidget(2, 1, button);
var handler = app.createServerHandler('ifCheck');
var handler = app.createServerClickHandler('ifCheck');
handler.addCallbackElement(myCheckBox);
myCheckBox.setValue(false, false);
handler.addCallbackElement(grid);
button.addClickHandler(handler);
panel.add(grid);
app.add(panel);
ss.show(app);
return app;
}
function ifCheck(e) {
var bCBresult = e.parameter.myCheckBox;
var app = UiApp.getActiveApplication();
Browser.msgBox(bCBresult);
if (bCBresult) {
Browser.msgBox("bCBresult = true");
}
else {
Browser.msgBox("bCBresult = false");
};
return app.close();
}
the value returned by e.parameter.myCheckBox is a string, not a boolean. (that's actually the case for all e.parameter values..., they are always strings)
So your condition would be if (bCBresult=='true') {