Access data in NSDictionary using Swift - ios

What's the syntax in Swift to access value of gross element?

You would be better pasting the console log as it's easier to understand.
But you should be able to do...
var results = //your dictionary
let gross = results["data"]["gross"]

var result = results["data"]["gross"]

Related

Converting a Swift UnsafePointer<AudioStreamBasicDescription> to a Dictionary?

I want to know how to create a dictionary of [String:AnyObject] from an UnsafePointer<AudioStreamBasicDescription>
I guess I don't understand how to work with an UnsafePointer<T> in Swift. Here's where I'm starting from - The AVAudioFile class has a fileFormat property which is of AVAudioFormat Type. AVAudioFormat has a streamDescription property which returns an UnsafePointer<AudioStreamBasicDescription> as a read-only property.
I'd like to see what the values are in this struct and converting to a Dictionary seems like it might be reasonable goal. In fact, there already seems to be a "settings" property on the AVAudioFormat Class that does this but I'm interested in understanding the "right way" to access the values stored in the UnsafePointer myself.
From the docs
Discussion: Returns the AudioStreamBasicDescription (ASBD) struct, for use with lower-level audio APIs
https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVAudioFormat_Class/index.html
Is there a way to do an unsafe conversion after checking if the struct is not nil? Would I use an unsafeBitCast here? I'm hesitant to jump into this too much as I've read that it's "extremely dangerous"...
I realize I can access the underlying memory with the following:
let audioFileURL:NSURL = NSBundle.mainBundle().URLForResource("FILENAME", with Extension: "mp3")
var file:AVAudioFile?
do {
file = try AVAudioFile(forReading: audioFileURL)
guard let file = file else {
fatalError("file must not be nil")
}
}catch {
print(error)
}
let format = file.processingFormat
let asbd:AudioStreamBasicDescription = format.streamDescription.memory
Is that dangerous and would I need to dealloc for some reason after creating the asbd constant?
I've tried to follow along with the post here http://sitepoint.com/using-legacy-c-apis-swift but I'm just not getting it... Looking for any direction on best practices here.
Update:
Doing a bit more research, it seems that it might be possible to create the dictionary using reflect based off this post: http://freecake.angelodipaolo.org/simple-reflection-in-swift/
Here's what I have so far:
let asbdMirror = reflect(asbd)
var asbdDict = [String: Any]()
for i in 0..<asbdMirror.count {
let (propertyName, childMirror) = asbdMirror[i]
asbdDict[propertyName] = childMirror.value
}
Any reason this is a bad idea?
You are doing everything correctly, you can access all the values in the description with asbd.mSampleRate and such. It wouldn't make sense to convert it to a dictionary because that's just not what it is, there are no keys for the values.
You also don't have to dealloc anything when working with pointers like this unless you allocate one yourself (when using malloc or alloc)

Realm not writing correctly

I've been trying to use Realm to create a db for my cocos2d game, but can't figure out some problem. I'm using Realm Objective-C 0.92.3 (https://realm.io/docs/objc/latest/) since I need my game to work on iOS 7 or later.
I've been using some small code to write and read but somehow it isn't working.
let realm = RLMRealm.defaultRealm()
var tempo = EnemyDB()
tempo.damage = 7
realm.beginWriteTransaction()
realm.addObject(tempo)
realm.commitWriteTransaction()
var temp = EnemyDB.allObjects()
Somehow this is returning empty object (temp = RLMResults! Unevaluated query on 0x00007f954708a070), does anyone see any problem?
Thank you for any help
EDIT:
import Foundation
class EnemyDB : RLMObject {
var damage : Int!
}
You might need to explicitly set a default value for the value of damage in EnemyDB.
Try changing it to this, and let me know if that works!
class EnemyDB : RLMObject {
var damage: Int = 0
}
this occurred with me and finally I figured out that my query string was not complete, by printing my predicate to the console as below.
Objective-C:
NSLog(#"%#",searchPredicate);
Swift:
print(\(searchPredicate)
It printed "SELF.message CONTAINS nil".
nil was the issue here. I fixed it and problem was gone.
Check for the same issue in your case.

componentsSeparatedByString method in Swift

I had some troubles last night accessing the elements of an array created via the componentsSeparatedByStringMethod. My goal is to extract some information from an url content variable.
var arr = urlContent.componentsSeparatedByString("<span class=\"Some HTML class\">")
I printed arr to the log, it works perfectly
I'd like to access the second element of the array arr, in order to get the info I need (the information right after the span tag). I thought:
var info = arr[1]
would work, but it doesn't. I get an error message saying that the subscript method doesn't work for an object of type "AnyObject" or something similar. So the problem is arr is not an Array Object type but an AnyObject type. I tried to convert it to an array but it didn't work either.
Could anybody help through this little trouble? :)
In xcode 6.1.1 componentsSeperatedByString method returns [AnyObject]. You have to cast it to [String] like so:
if let arr = urlContent.componentsSeparatedByString("<span class=\"Some HTML class\">") as? [String] {
// arr is now [Sstring]
}
In xcode 6.3 beta this method returns [String] so cast is not needed.

Swift Int is not convertible to DictionaryIndex?

I'm trying to convert this piece of ojb-c code:
MPMovieFinishReason finishReason = [notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] integerValue];
to swift, and as such I have this:
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey.integerValue];
However this gives me the error in the title.
What am I doing wrong here?
You have a few problems, first of all in your direct translation:
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey.integerValue];
The ] is in the wrong place, so you're trying to call integerValue on MPMoviePlayer... instead of on the dictionary lookup.
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey].integerValue;
This is still failing because userInfo is an NSDictionary and not a Dictionary, so it gets mapped to [AnyObject:AnyObject] It seems like the automatic morphing is failing you, so it's falling back to a CFString which isn't mappable to AnyObject.
The process becomes a little clearer if we break it up more:
// Recover the original dictionary, and cast is by input and output, to it
// all makes sense. This will allow String as a parameter and return an NSNumber
// as a result.
let userInfo = notification.userInfo as [String:NSNumber]
// From the userInfo, let's extract the raw NSNumber using lookup
let reason = userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]
// Convert the NSNumber into an MPMovieFinishReason enum. Note that it's
// 0215 and I'm on ambien so I don't care about the force unwrapping that
// should be optional unwrapping
let finishReason = MPMovieFinishReason.fromRaw(reason!.integerValue)
Many problems can be broken down into much simpler problems if you just take it a single step at a time. Modern compilers aren't even too bothered by it as the can recognize when variables are no longer in use and do proper reclamation. Also note using let instead of var for those temporary values since they shouldn't be reused anyway.
Try the type-casting function Int()
ie.,
var finishReason = Int(notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]) as MPMovieFinishReason;

Swift equivalent to `initWithContentsOfFile:`?

I am trying to use the Swift equivalent of initWithContentsOfFile: on an Array. The documentation states that the equivalent is convenience init(contentsOfFile aPath: String!)
I have tried to call this with the following code:
var path = NSBundle.mainBundle().pathForResource("Standards", ofType: "plist")
var rawStandards = Array<Dictionary<String, AnyObject?>>(contentsOfFile: path)
The compiler is telling me, however, that it couldn't find an overload that accepts the supplied arguments. What am I missing?
#Leo Natan was really close, but the way that worked for me was:
var rawStandards = NSArray(contentsOfFile: path)
I was then able to access the elements:
for obj: AnyObject in rawStandards {
if var rawStandard = obj as? NSDictionary {
}
}
You are initializing a Swift array, not an NSArray, which has the initWithContentsOfFile: initializer method.
Try:
var rawStandards = NSArray(contentsOfFile: path) as Dictionary<String, AnyObject?>[]
var path = NSBundle.mainBundle().pathForResource("Standards", ofType: "plist")
var menuItemArray = NSArray(contentsOfFile: path) as NSArray!
this is what i'm using myself. in viewDidLoad
Here is what worked for me. I've verified it in the beta build of Xcode. Unlike the other answers, I wanted a native typed Swift array with the results, so I took a few extra steps. (#wayne-hartman's answer may be more intuitive if you don't know what you have in your plist or don't want a typed Array.) It did require forcing types in a way I didn't expect.
My plist has dictionaries at the first level and strings at the second level, the code should be easy to adjust for other types.
let plistNSArray = NSBundle.mainBundle().pathForResource("myplist", ofType: "plist")
let untypedArray: AnyObject[] = plistNSArray
let typedArray = untypedArray as Dictionary<String,String>[] //Obviously you could do this conditionally for better error handling
for plistDictItem in typedArray {
for (dictKey,dictValue) in plistDictItem {
println("key \(dictKey) has value \(dictValue)")
}
}
It doesn't work (or at least I couldn't make it work) without the intermediate step of untypedArray.
#leo-natan's doesn't compile for me, even though it looks like it should to me. I believe that the compiler just can't automatically convert the NSArray into a typed Swift array directly without the intermediate step I added. It wouldn't surprise me if his code works in a future release.

Resources