Swift App - casting from AnyObject to NSArray seems to fail - ios

I posted this question on the Apple IOS Developers' Forum, with a notable lack of response. I'm hoping the StackOverflow wizards can help...
I'm developing an iOS 8 app using Swift. In Xcode beta 5 the code below code worked, but gives me a linker error in beta 6 and beta 7:
var sqlStr = "SELECT count(*) as count FROM nouns WHERE bucket = ?;"
var rs = db.executeQuery(sqlStr, withArgumentsInArray: [0] as NSArray)
The linker error is:
Undefined symbols for architecture x86_64:
__TFSs26_forceBridgeFromObjectiveCU__FTPSs9AnyObject_MQ__Q_", referenced from:
__TFC8les_Mots13WordGenerator9getBucketfS0_FT_Si in WordGenerator.o
(getBucket is a method in the UIViewController WordGenerator. If I reduce the method to just these two lines, I get the same error, and if I comment these two lines out, the error goes away, so I know the problem is here.)
The db.executeQuery() is an FMDB method with this signature:
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
If I change the code to this, it works in all betas:
var sqlStr = "SELECT count(*) as count FROM nouns WHERE bucket = '\(whereClause)';"
var rs = db.executeQuery(sqlStr, withArgumentsInArray: nil)
From the linker error and my trials-and-efforts to debug this, it appears that the cast of [0], which is of type AnyObject to an NSArray, which is required, is failing. I'm using this example, but I'm seeing similar problems in other areas of the app, all where an AnyObject has to be cast to an NSArray or NSDictionary.
The original code above works just fine in Xcode beta 5, but not in subsequent betas. Clearly I'm not understanding something about the AnyObject to NSArray cast, but I'm darned if I know what, and it appears that betas 5 and 6 enforce something not previously enforced. I've tried every kind of explicit cast I can think of, with no success.
Any help will be GREATLY appreciated.

I changed the Build location and the code now compiles, links and runs. Previously the Build location was Custom/relative to workspace; I changed it to Unique.
I have no idea why this would change things, as I had deleted derived data and cleaned the build folder many times. But...it worked, so if anyone is having the same problems, give this a try.

Related

Strange errors after converting SceneKit sample code to Swift 3

I downloaded Apple's SceneKit sample code (fox.swift) and opened it up on Xcode 8 beta 6.
It asked me to convert the code to Swift 3, which I did.
When I try to run the code on my phone I receive the errors:
Value of type ‘SCNNode’ has no member ‘run’
Value of type ‘SCNNode’ has no member ‘add’
Sample lines where the error occurs:
cameraYHandle.run(actionY)
self.cameraYHandle.add(cameraYAnimation, forKey: nil)
This leads me to three questions:
1) Are the functions 'run' and 'add' gone on SCNNode for Swift 3?
2) If so, what should I replace them with?
3) If so, if so, why didn't Xcode's converter handled them already?
Thank you for your time :)
PS.: It runned well for Mac using Xcode 7.3.
As dan commented, these translations resulted in a code without errors:
run => runAction
add => addAnimation
play => playAudio
so,
cameraYHandle.run(actionY) becomes cameraYHandle.runAction(actionY)
and so on.
Thank you, Dan.

Xcode 8.0 Swift 3.0 slow indexing and building

I've installed Xcode 8.0 and converted Swift 2.2 to 3.0 (that process also took a lot of time, I just left my Mac running all night). I have not a big project (about 20 files). I am also using Pods. Indexing of previous Xcode version (< 8.0) worked fast but now, after upgrade, the progress bar is stuck on one position (I am already waiting for an hour).
Things I've tried that didn't help me:
Cleaned the DerivedData folder and restarted Xcode
Cleaned the project and restarted Xcode
Deleted Pods directory with <project>.xcworkspace and then installed again
Restarted Mac
Tried build project without Pods
Reinstalled Xcode
Tried on another Mac with cloned project
It is really not cool to make such releases of software when developers have to spend hours on solving such ridiculous problems. It is very disappointing.
Any ideas how to fix this?
Go to project settings, then Editor > Add Build Setting > Add User-Defined Setting, and add the following:
SWIFT_WHOLE_MODULE_OPTIMIZATION = YES
Adding this flag dropped our clean-build compile times from 7 mins to 65s for a 40KLOC swift project, miraculously. Also can confirm 2 friends have seen similar improvements on enterprise projects.
I can only assume this is some kind of bug in Xcode 8.0
I solved the problem by commenting all files and then removing comments one by one. I found that the problem is still in the array declaration as described here.
I had code like this and project was not indexing:
class {
var first: String!
var second: String!
var third: String!
var fourth: String!
var fifth: String!
func abc() -> [String] {
var array = [first, second, third, fourth, fifth]
}
}
I've changed it to this and indexing started working:
class {
var first: String!
var second: String!
var third: String!
var fourth: String!
var fifth: String!
func abc() -> [String] {
var array = [first]
array.append(second)
array.append(third)
array.append(fourth)
array.append(fifth)
}
}
I've had the same issue only since upgrading to Swift 3/XCode 8 and it seems to be caused by large array literals.
I was able to fix the issue by adding type annotations to the variables being assigned to the array literal, e.g.
let array: Array<String> = ["1", "2", "3", "4", "5", "6", "7", "8"]
instead of
let array = ["1", "2", "3", "4", "5", "6", "7", "8"]
I had similar problem and followed this guide to debug : http://irace.me/swift-profiling
My problem was i had nil coalescing operator in some strings for example:
let name = "\(someString ?? "")"
and four methods with this were causing 2 min additional building time.
I had the same problem and solved it by painstakingly going through my code line by line, it turns out Swift 3 prefers string interpolation rather than using the + symbol, i.e.
let url = "http://yahoo.com" + "someWebPage" + "whereItsInteresting"
If you have been using the above style of code replace it for;
let url = "http://yahoo.com\(someWebPage)\(whereItsInteresting)"
And your build time will immediately come back to normal.
for those who want to find where compiler is "caught"
Add to Other Swift Flags -Xfrontend -warn-long-function-bodies=50
check full answer here
I tried the above solutions but the problem still happens. The debugging works weird, too. After some days research I found the solution below.
Select main target > Build Settings. Configuring as image below.
I encountered the same indexing issue, but it occurred only when I was running/debugging on a device and then switched to another device on the top-left toolbar (Target > iPhone).
None of the solutions above worked for me.
My solution: I removed my local git working copy and cloned a new one from my 'origin'.
(There are some 'magic' files within the xcuserdata/shared/session etc. folders that may have caused this issue?)
Not that I think this is related to OP's issue, but XCode 8 for me recently slowed to a halt. I eventually found it was my mistake (and I remember inadvertently doing it) - I added XCode.app as a Framework reference. This essentially made XCode search and index the entire XCode.app folder. Once I saw the mistake and remove the Framework it came good again :)
I had a function that took over a minute to compile, and after some investigation, I found that the culprit was checking if enough time had elapsed from a stored date:
let myStoredDate: Double = // Double representing a time in the past
// if at least one week (60 * 60 * 24 * 7 seconds) has passed since myStoredDate
if Date().timeIntervalSince1970 - myStoredDate > (60 * 60 * 24 * 7){
// do stuff
}
This code would take over 10 seconds to compile — coupled with this code being repeated with different numbers multiple times, it was causing compilation to take way too long. I was able to fix this by pre-computing the interval
let myStoredDate = // Double representing a time in the past
//it is important to explicitly specify that the variable is a Double
let interval: Double = 60 * 60 * 24 * 7
if Date().timeIntervalSince1970 - myStoredDate > interval{
// do stuff
}
After doing this with the ~10 times I was checking, the compilation time was cut from over a minute to just a few milliseconds.
It's extremely likely that this problem also occurs with the combination of type-inferance and math elsewhere, so ensure that nothing like this happens anywhere else in your code.
My problem was the dictionary. I had vary large dictionary.
let values = ["address":addressTextField.text,"city":cityTextField.text,"zipCode":zipCodeTextField.text,"state":stateTextField.text,"pet":answerLabel.text,"rentStart":rentStartTextField.text,"rentEnd":rentEndTextField.text,"rent":rentTextField.text,"phone":phoneTextField.text,"email":emailTextField.text,"status":leaseStatusTextField.text,"bedrooms":bedroomTextField.text,"parking":parkingLabel.text,"furnish":furnishLabel.text,"utilities":utilitiesTextField.text,"laundry":laundryTextField.text,"paymentCycle":paymentCycleTextField.text,"note":noteTextView.text]
I broke it down to:
var values = ["address":addressTextField.text]
values["city"] = cityTextField.text
values["zipCode"] = zipCodeTextField.text
values["state"] = stateTextField.text
values["pet"] = answerLabel.text
values["rentStart"] = rentStartTextField.text
values["rentEnd"] = rentEndTextField.text
values["rent"] = rentTextField.text
values["phone"] = phoneTextField.text
values["email"] = emailTextField.text
values["status"] = leaseStatusTextField.text
values["bedrooms"] = bedroomTextField.text
values["parking"] = parkingLabel.text
values["furnish"] = furnishLabel.text
values["utilities"] = utilitiesTextField.text
values["laundry"] = laundryTextField.text
values["paymentCycle"] = paymentCycleTextField.text
values["note"] = noteTextView.text
values["owner"] = userID
Backup your project delete the last update project after backup and then restart Xcode simple :-)
After add the setting,
SWIFT_WHOLE_MODULE_OPTIMIZATION = YES
our project clean-build compile times from 1200s to 180s for 650 swift files. But this will cause increase compile fail. Every change need 180s to compile when increase compile only need 60s
It's a Xcode bug (Xcode 8.2.1) and it will happen when you have a large dictionary literal or a nested dictionary literal. You have to break your dictionary to smaller parts and add them with append method until Apple fixes the bug.
This works for me in Xcode 8.2.1 and Swift 3 when "Indexing" is stuck:
I always have two projects open, a dummy project and the project I'm working on. I also have a iPad Air device connected that I run my projects on. When my project gets stuck on "Indexing", I switch to my dummy project and run my project on my connected iPad Air device. Then I stop the project
and switch back to the project I'm working on and the "Indexing" is magically finished. This should also work with the simulator only, if you don't have a physical device connected.
I've had similar problems and developed my own utility 🏈 Rugby.
In the current version, Rugby can cache all remote pods dependencies and remove their targets from the Pods project.\
Under the hood, it's using some optimizations. For example, like SWIFT_COMPILATION_MODE=wholemodule.
What solves this for me is using keys to set dictionary values
let dict: [string:any]()
dict["key"] = "value"
dict["key1"] = "value"
dict["key2"] = "value"
return dict
If you have a long dictionary it may or may not cause a compile loop resulting in long build times. Anything longer than 8 keys should be set way.

Stanford calculator app crashes with error "unexpectedly found nil"

I'm new to programming and I've started taking the stanford course on iTunes U for making an iPhone 8 app. They're using Xcode 6 and Swift 1 while I'm in El Capitan using Xcode 7 and Swift 2. I've found a few differences in code that Xcode has been able to pick up on and help me correct ("println" is now "print" for example), but I'm getting tripped up on one particular part of the code:
var displayValue: Double {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTypingANumber = false
}
}
I've double checked several times to make sure this is exactly how the teacher wrote it. His built correctly and functioned correctly, while mine builds correctly, but shows this fatal error when I try to operate it, "unexpectedly found nil while unwrapping an Optional value" (see screenshot for all the details).
Screenshot of the error
I've been looking around the internet and found a few similar examples, including one on this site (Stanford Calculator app keeps crashing), but after trying everything that was suggested I concluded that something must be unique in my system or I'm operating in a new Xcode/Swift environment than the others that had this problem. None of the solutions have resolved the problem, and all of them added errors of their own.
In responding to someone else's question someone suggested that we use this code to ensure that if "nil" is returned by "display" that it will provide "0" instead:
return (NSNumberFormatter().numberFromString(display.text) as? Double) ?? 0
I tried this, but it only gave me more errors, some seem to be related to Swift 2 (it required a comma after double, wanted me to unwrap display.text, and complained that there was an expected expression missing—maybe the suggested code was good in Swift 1??).
I've double checked several times to make sure this is exactly how the teacher wrote it. His built correctly and functioned correctly, while mine builds correctly, but shows this fatal error when I try to operate it, "unexpectedly found nil while unwrapping an Optional value"
I suspect that display is an IBOutlet property that needs to be connected to something in the user interface, probably a text field. If it's not connected, then even though your code is exactly the same, you'll get nil when you try to use its text property, and unwrapping that will cause the error you're seeing.
Whether or not the advice above actually solves your problem, what you really need to do is to set a breakpoint a line or two before the spot where the crash occurs and step through the code. Look at the variables involved and figure out where that nil value is coming from. You can work backward from there and figure out why the thing that you expect not to be nil is, in fact, nil. Learning to work that way will help you work out these kinds of problems when they occur (and they will occur again).
Not sure if you've found the answer or not by now, but I ran into a similar problem this morning and thought I'd share what I found.
While debugging, I entered two console logs to a simplified version of my operate like so:
case "x": if operandStack.count >= 2 {
print(" display before popping is: \(display.text!) ")
displayValue = operandStack.removeLast() * operandStack.removeLast()
print(" display after popping is: \(display.text!) ")
enter()
}
Display after popping came up as "newValue". I couldn't figure out what that meant at first, but realized that my issue is the setter. newValue is an optional that should be unwrapped i.e. "(newValue)!"
P.S. I opted to return:
return (display.text! as NSString).doubleValue
in my get.
Also, since newValue is unwrapped, keep in mind it will crash if display is set to nil.

EXC_BAD_ACCESS when updating Swift dictionary after using it for evaluate NSExpression

I'm using a dictionary to evaluate an expression, when the expression has variables and the dictionary is actually used by NSExpression, something happens and I get EXC_BAD_ACCESS when trying to update the dictionary, this only happens when debugging in an iPhone6, not in the simulator and not in an iPhone 4S.
let strExpression = "a+b+20"
let exp = NSExpression(format:strExpression)
self.dictionary = ["a":10.0, "b":15.0, "c":25.0]
let value:AnyObject = exp.expressionValueWithObject(self.dictionary, context: nil)
let doubleValue = value as Double
self.dictionary.updateValue(doubleValue, forKey: "c")
Something really weird is that if i add this line just after creating the dictionary, then it woks fine:
let newDic = self.dictionary
I,m using iOS 8.1. Thanks in advance!
With #bensarz comment, I thought it might be helpful for others searching for answers if I put the response into an actual answer instead of a comment.
Per #LeeWhitney's response on a similar post:
Looks like a compiler bug.
Have you tried switching between Release and Debug then rebuilding? If debug works but not release it can be an indication of a compiler/optimizer bug.
Does it happen in the simulator also?
Your code works for me on iOS 8.1 with XCode 6.1.
Solution:
The issue seems to be solved by changing the 'Optimization Level' under the 'Swift Compiler - Code Generation' to 'None'. The issue seems to be with the 'Fastest' Compiler optimization level.
Also, a work around that I've found original before the compiler change:
If you use a let statement prior to assigning values in the dictionary, it seems to alleviate the issue. More information found at link below:
EXC_BAD_ACCESS on iOS 8.1 with Dictionary

JSONKit Crash: iOS7 Xcode 5.1 in iPad ratina 64 bit device simulator

I have used JSONKit library to parse dictionary and get JSON string. All is well and good with normal devices (iOS7). But when i run application in iOS 7-64 bit simulator it was crashed at below method:
- (NSString *)JSONString;
And the crash message shows on this line of JSONKit.m class
Tried to find out it but not able to sort out.
And i ended up with our native NSJSONSerialization class.
Did any one sort out this?
As far as I know there are more than one patch versions that tried to fix the 64 bit crash issue you mention here, e.g. JSONKit 64bit crash fix by heroims.
They all tried to fix that troublesome line for getting tagged pointers, "the very first thing that a pointer to an Objective-C object "points to" is a pointer to that objects class":
*((void **)objectPtr)
I wrote a simple code to emulate the crash,
NSDictionary *dic = #{#"hi":#(4)};
void *keys[2], *objects[2];
CFDictionaryGetKeysAndValues((CFDictionaryRef)dic, (const void **)keys, (const void **)objects);
void *objectPtr = objects[0];
void *another = *((void **)objectPtr);//Only works for 32 bit machine
NSLog(#"%#",[another description]);
My guess is that for 64bit compiler, apple changed the tagged pointer implementation for NSNumber, which causes the crash. Check the discussion for tagged pointers here stackoverflow.com/questions/5819387/why-is-nsnumber-immutable
If I change NSDictionary *dic = #{#"hi":#(4)}; to NSDictionary *dic = #{#"hi":#"hello"}; it won't crash.
The patch I mentioned here just used object_getClass, which seems to defeat the original purpose, "Why not just use object_getClass()?..." (the comments right above)
So like you said now I also end up using NSJSONSerialization class.
There is an patched version of JSONKit here that fixes the 64 bit issues among others.

Resources