Variable contains nil value in Swift 2 - variables

I declared a variable destinationID on top of my class. The first print shows the right content of the variable while the second one has a nil value.
Does anyone know what the problem is?
import UIKit
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate{
var destinationUserID = String()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
//Opzoeken wat het bijhorende ID is
let query = PFQuery(className:"_User")
query.whereKey("username", equalTo:selectedUsername)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
// Do something with the found object
for object in objects! {
self.destinationUserID = object.objectId!
print(self.destinationUserID)
}
print("try 1 : " + self.destinationUserID)
}
print("try 2 : " + self.destinationUserID)
}
}

The print("try 1... statement is inside the block. The print("try 2... is outside the block. The block is executed in the background which means that the search might not have completed when you get to print("try 2....

Related

'unrecognized selector' for category method on SpriteKit class [duplicate]

I'm creating a game with SpriteKit, that has collision between 2 bodies. After setting up the bodies, I've implemented the didBegin(_contact:) moethod as shown below:
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 {
gameOver()
}
}
and it worked perfectly.
Later, while inspecrting the documentation for this method, I found the following:
The two physics bodies described in the contact parameter are not passed in a guaranteed order.
So to be on the safe side, I've extended the SKPhysicsContact class with a function the swaps the categoryBitMask between both bodies, as following:
extension SKPhysicsContact {
func bodiesAreFromCategories(_ a: UInt32, and b: UInt32) -> Bool {
if self.bodyA.categoryBitMask == a && self.bodyB.categoryBitMask == b { return true }
if self.bodyA.categoryBitMask == b && self.bodyB.categoryBitMask == a { return true }
return false
}
}
The problem is that when the function gets called, the app crashes, and I get the following error:
2017-07-18 13:44:18.548 iSnake Retro[17606:735367] -[PKPhysicsContact bodiesAreFromCategories:and:]: unrecognized selector sent to instance 0x60000028b950
2017-07-18 13:44:18.563 iSnake Retro[17606:735367] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsContact bodiesAreFromCategories:and:]: unrecognized selector sent to instance 0x60000028b950'
This apparently is a bug, as answered here:
https://stackoverflow.com/a/33423409/6593818
The problem is, the type of contact is PKPhysicsContact (as you've noticed), even when you explicitly tell it to be an SKPhysicsContact, and the extension is on SKPhysicsContact. You'd have to be able to make an extension to PKPhysicsContact for this to work. From this logic, we can say that no instance methods will work in SKPhysicsContact extensions at the moment. I'd say it's a bug with SpriteKit, and you should file a radar. Class methods still work since you call them on the class itself.
In the meantime, you should be able to move that method into your scene or another object and call it there successfully.
For the record, this is not a Swift-specific problem. If you make the same method in an Objective-C category on SKPhysicsContact you'll get the same crash.
You can submit a bug report to apple:
https://developer.apple.com/bug-reporting/
And report it to the community:
https://openradar.appspot.com/search?query=spritekit
However, what you really want to do with your code is to add the category masks together. And then check for the sum (2 + 4 and 4 + 2 always equals 6, regardless of bodyA and bodyB order).
This is how you get unique contacts, if you set up your masks correctly in powers of two (2, 4, 8, 16, etc)
SKPhysicsContact is a wrapper class to PKPhysicsContact, you are extending SKPhysicsContact but in reality you need to extend PKPhysicsContact (Which you can't do)
To preserve order in your contact methods, just do:
let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
This way when you need to check for a specific node, you know what node to hit, so
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == 0 && contact.bodyB.categoryBitMask == 1 {
gameOver()
}
}
Becomes
func didBegin(_ contact: SKPhysicsContact) {
let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
if bodyA.categoryBitMask == 0 && bodyB.categoryBitMask == 1 {
gameOver()
}
}
You can then add to your code since you now know the individual bodies.
func didBegin(_ contact: SKPhysicsContact) {
let bodyA = contact.bodyA.categoryBitMask <= self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
let bodyB = contact.bodyA.categoryBitMask > self.bodyB.categoryBitMask ? contact.bodyA : contact.bodyB
if bodyA.categoryBitMask == 0 && bodyB.categoryBitMask == 1 {
gameOver()
//since I know bodyB is 1, let's add an emitter effect on bodyB.node
}
}
BTW, for people who see this answer, categoryBitMask 0 should not be firing any contacts, you need some kind of value in it to work. This is a bug that goes beyond the scope of the authors question, so I left it at 0 and 1 to since that is what his/her code is doing and (s)he is claiming it works.

Application crashes while saving core data in iOS11

Works perfectly in iOS 10. After I updated my iOS to iOS11 the application is crashing while saving data to core data with an exception.
I have used RZVinyl framework for coredata
BOOL isSaved = [currentContext save:&saveErr];
Assertion failed: (moreParameters->mostRecentEntry ==
CFArrayGetValueAtIndex(stack, stackCount - 1)), function
NSKeyValuePopPendingNotificationPerThread, file
/BuildRoot/Library/Caches/com.apple.xbs/Sources/Foundation_Sim/Foundation-1444.12/EO.subproj/NSKeyValueObserving.m, line 933.
0 libsystem_kernel.dylib 0x00000001826fd348 __pthread_kill + 8
1 libsystem_pthread.dylib 0x0000000182811354 pthread_kill$VARIANT$mp + 396
2 libsystem_c.dylib 0x000000018266cfd8 abort + 140
3 libsystem_c.dylib 0x0000000182640abc basename_r + 0
4 Foundation 0x00000001834f1a9c -[NSRunLoop+ 178844 (NSRunLoop) runUntilDate:] + 0
5 Foundation 0x00000001834df538 NSKeyValueDidChange + 436
6 Foundation 0x0000000183597ae4 NSKeyValueDidChangeWithPerThreadPendingNotifications + 140
7 CoreData 0x00000001854107c8 -[NSManagedObject didChangeValueForKey:] + 120
8 CoreData 0x0000000185416358 -[NSManagedObject+ 844632 (_NSInternalMethods) _updateFromRefreshSnapshot:includingTransients:] + 692
9 CoreData 0x000000018542e054 -[NSManagedObjectContext+ 942164 (_NestedContextSupport) _copyChildObject:toParentObject:fromChildContext:] + 652
10 CoreData 0x000000018542e4bc -[NSManagedObjectContext+ 943292 (_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 804
11 CoreData 0x000000018542f3f0 __82-[NSManagedObjectContext+ 947184 (_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 580
12 CoreData 0x0000000185431644 internalBlockToNSManagedObjectContextPerform + 92
13 libdispatch.dylib 0x0000000182569048 _dispatch_client_callout + 16
14 libdispatch.dylib 0x0000000182571ae8 _dispatch_queue_barrier_sync_invoke_and_complete + 56
15 CoreData 0x000000018541dd10 _perform + 232
16 CoreData 0x000000018542f0e4 -[NSManagedObjectContext+ 946404 (_NestedContextSupport) executeRequest:withContext:error:] + 172
17 CoreData 0x0000000185387ff8 -[NSManagedObjectContext save:] + 2580
NSManagedObjectContext *currentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[[currentContext userInfo] setObject:self forKey:kRZCoreDataStackParentStackKey];
[self performBlock:^{
BOOL hasChanges = [currentContext hasChanges];
if ( !hasChanges) {
RZVLogInfo(#"Managed object context %# does not have changes, not saving", self);
rzv_performSaveCompletionAsync(completion, nil);
return;
}
NSError *saveErr = nil;
BOOL isSaved = [currentContext save:&saveErr];
if ( !isSaved) {
RZVLogError(#"Error saving managed object context context %#: %#", self, saveErr);
rzv_performSaveCompletionAsync(completion, saveErr);
}
}];
Had the same thing right now and was looking for an answer when I came across your question.
Without any answers to be found I did some in-depth investigation and found the cause (at least in my case).
It turned out that one of the object's relationships was observing KV changes to update the object regarding changes to it's values, and it was also updating a change to the value of the relationship.
That triggered and update on the Object, which caused the relationship to updated with a change, and so on and so forth...
This recursion in KVO caused a crash.
Make sure that if you are observing changes via willChangeValue and didChangeValue to update your relationship regarding this change, don't update if the observer is the one being set.
Does that make sense for you?
Let me know if this is the case and you need a code sample to understand this very confusing answer.
UPDATE:
I know my answer is quite confusing and vague, so I'll add an example.
Consider the following.
We have two example classes which has relationship to each other (i.e reverse relationship):
class A: NSManagedObject {
#NSManaged var id: NSNumber!
#NSManaged var title: String?
#NSManaged var b: B!
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
b?.willChangeValue(forKey: "a")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
b?.didChangeValue(forKey: "a")
}
}
class B: NSManagedObject {
#NSManaged var id: NSNumber!
#NSManaged var name: String?
#NSManaged var date: Date?
#NSManaged var a: A!
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
a?.willChangeValue(forKey: "b")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
a?.didChangeValue(forKey: "b")
}
func setNewA(_ newA: A) {
newA.b = self
a = newA
}
}
We use willChangeValue and didChangeValue in each class to notify it's relationship regarding changes in itself.
Now consider the following code:
let b = B(context: context)
let a = A(context: context)
b.setNewA(a)
We use the setNewA function to set the reverse reference.
In the function, first b assigns itself to a.b for the reverse reference and then sets self.a reference.
At this point, a already knows about b.
The later will cause willChangeValue and didChangeValue on b to be called (as we set a). Then a will pick up the update and notify b.
From here on, try can guess how it continues.
This was pretty much what happened to me, with a few minor differences.
I overrode these functions because I am using a NSFetchedResultsController and I needed to pick up on changes in the relationships to update my UI.
It threw me in a loop that caused the crash.
At the end, the fix was rather simple. A was modified to be:
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
guard key != "b" else { return }
b?.willChangeValue(forKey: "a")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
guard key != "b" else { return }
b?.didChangeValue(forKey: "a")
}
and B was modified the same way, to be:
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
guard key != "a" else { return }
a?.willChangeValue(forKey: "b")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
guard key != "a" else { return }
a?.didChangeValue(forKey: "b")
}
This prevents each from updating the other once the relationship itself is set (which is redundant, as each is already notified once one of it's properties is set), thus breaking the cycle.
Again, this was the case on my end and this is what fixed it.
Don't know if you're experiencing the issue due to the same reason, but hopefully it'll give you an idea where to look.
Hope it's easier to understand now.
If you're still having trouble understanding, share some code or contact me directly and I'll try and help.

Sort indexPathsForSelectedRows in Swift

When you invoke tableView.indexPathsForSelectedRows(), it returns an array of AnyObject type with the indexPaths of the rows selected in the order that user has selected them.
What I want is to sort the indexPaths in order to get ascending order. Before Swift, it could be achieved with this:
NSArray *sortedIndexPaths = [[tableView indexPathsforSelectedRows]
sortedArrayUsingSelector:#selector(compare:)];
But I have tried to implement it with Swift and it does not work :S
Anyone knows how to deal with this?
Thanks in advance!
it's simple code to sort array of NSIndexPath objects stored in paths variable .
The trick is in casting to [NSIndexPath]. Now you can have your array sorted.
let paths = tableView.indexPathsForSelectedRows() as [NSIndexPath]
let sortedArray = paths.sorted {$0.row < $1.row}
OR
if you wish to have separate function for that like:
func compare (obj0: NSIndexPath, obj1: NSIndexPath) -> Bool {
return obj0.row < obj1.row
}
then
let sortedArray = paths.sorted { compare($0, $1) }
I'm on Windows 7 at the moment so I cannot test but this is what I would expect to work. It may need a type annotation.
let paths = tableView.indexPathsforSelectedRows()
let sorted = paths.sortedArrayUsingSelector("compare:")
You can overload the < and > operators and then just call sort on it.
Define this globally
func <(left: NSIndexPath, right: NSIndexPath) -> Bool {
return left.section < right.section || left.row < right.row
}
Then you can just do this for ascending
let sortedIndexPaths = tableView.indexPathsForSelectedRows?.sort(<)
Obviously because of it returns an optional you would guard against it somehow, for example
guard let sortedIndexPaths = tableView.indexPathsForSelectedRows?.sort(<) else {
return
}
Here is Sort indexPathsForSelectedRows swift 4 code.
if var selection = tableView.indexPathsForSelectedRows
{
selection = selection.sorted{ $1.compare($0) == .orderedAscending }
}
If you have any issue ping me.

how to use AXUIElementCopyAttributeValue from Swift?

I am trying to use AXUIElementCopyAttributeValue from Swift. My best stab currently looks like this:
private func mainWindow() -> Optional<AXUIElementRef> {
let appRef = AXUIElementCreateApplication(self.pid())
var ptr: Unmanaged<AXUIElementRef>? = nil
var frontWindow: AXUIElementRef? = nil
let err = AXUIElementCopyAttributeValue(appRef, kAXMainWindowAttribute, &ptr)
if err == AXError(kAXErrorSuccess) {
frontWindow = ptr!.takeRetainedValue()
}
return frontWindow
}
Unfortunately kAXMainWindowAttribute is not in scope. This works in ObjC of course, but I can't figure out where the value is hiding when accessed from Swift. This isn't the first time I've had this problem, either, although previously I've been able to stumble around a bit and find it.
Also, I'd be happy to receive any stylistic suggestions here. I'm not convinced I'm doing this in the most natural way for Swift.
It is an old question but I still drop it here in case someone else searches for it:
let appRef = AXUIElementCreateApplication(pid)
var value: AnyObject?
AXUIElementCopyAttributeValue(appRef, kAXMainWindowAttribute as CFString, &value)
also, I assume you get the "Swift dynamic cast failed" error message because you try to cast from AXUIElement to AnyObject. You can cast it like so:
print(value as! AXUIElement)
This is not an answer yet, but perhaps might help someone get me an answer... I changed the code to this, in order to make forward progress:
func mainWindow() -> WBWindow? {
var result: WBWindow? = nil
var ptr: Unmanaged<AnyObject>?
let kAXMainWindow: CFString! = "AXMainWindow" as NSString
let appRef: AXUIElement! = AXUIElementCreateApplication(self.pid()).takeRetainedValue()
let err = AXUIElementCopyAttributeValue(appRef, kAXMainWindow, &ptr)
if err == AXError(kAXErrorSuccess) {
let val: AnyObject? = ptr?.takeRetainedValue()
if val != nil {
let value: AnyObject = val!
let description = CFCopyTypeIDDescription(CFGetTypeID(value))
println("type = \(description)")
}
else {
NSLog("got nil result")
}
// result = WBWindow(element: ptr?.takeRetainedValue() as? AXUIElement)
}
return result
}
This now builds -- yay! But, when running, the commented out line drops me into a stack:
0x1001b57ea: leaq 0x3f1a1(%rip), %rax ; "Swift dynamic cast failed"
I added the debugging code above and that produces:
type = AXUIElement
Sooooo. It's an AXUIElement that won't cast to one? Clearly I'm missing something obvious...

Operations based on user input Swift

long question, so bear with me...
I am attempting to create a bitcoin ticker and converter written in Swift. I am using the code below (bits not related to conversion are removed - let me know if I left out anything important)
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var USD: UITextField! //Amount of USD. Originally equals 1 bitcoin, can be changed by user.
#IBOutlet weak var BTC: UILabel! //Amount of bitcoins the entered amount of USD is worth. Originally 1.
func handler(response: NSURLResponse!, data : NSData!, error : NSError!) { //To fetch Bitcoin Price. This is functional.
if ((error) != nil) {
self.USD.text = "No Internet" // in case of error
} else {
var price = NSString(data:data, encoding:NSUTF8StringEncoding)
self.USD.text = price //set USD to be equal to price of 1 Bitcoin
}
override func viewDidLoad() {
//Sets up view
self.update() //Fetches Bitcoin Price. This works.
self.convert() //Begins convert method
var timer = NSTimer.scheduledTimerWithTimeInterval(120, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
}
func convert() {
var url = NSURL(string:"https://api.bitcoinaverage.com/ticker/USD/last")
var request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:handler)
var data = NSData(contentsOfURL:url);
while true {
if USD.text != data {
BTC.text = USD.text / NSString(data:data, encoding:NSUTF8StringEncoding)// Attempts to determine amount of bitcoin the USD amount is worth. ERROR HERE!
}
}
On the line with the comment "ERROR HERE", I get the error
/Users/[My User]/Documents/dev/Newest Stuff/CryptoCoinTicker/CryptoCoinTicker/ViewController.swift:95:32: 'String' is not convertible to 'UInt8'
In case the code doesn't tell the story, I want BTC.text to change to be equal in value to the amount entered by the user in USD.text (so if a bitcoin is worth $500, and the user entered 250.00, BTC.text would say 0.5.
What do I need to do? Apologies for a (probably) basic question, I am but a newbie. Let me know if you ned more info.
Thanks in advance!
When you get that error, it usually means that you are trying to assign a wrong type to a variable or that you are using the wrong types for function parameters.
In your case, you are trying to divide two Strings. The compiler doesn't know what to do, since the division of Strings is not defined. You can only divide Int, Float and Double and you can't even mix them!
So for that line you can substitute this:
let value = NSString(string: USD.text).doubleValue / NSString(data:data, encoding:NSUTF8StringEncoding).doubleValue
BTC.text = "\(value)"
This first "converts" the USD.text to NSString and then converts both NSStrings to Doubles, which you can then divide.
It then creates a String from that value, which can be assigned to the BTC.text property.