I am accessing a plist file using the code below on a Cocoa with Objective-C application:
NSString *plistPath = [#"~/Library/Preferences/com.apple.mail.plist" stringByExpandingTildeInPath];
NSDictionary *plistData = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSArray *item = [plistData valueForKeyPath:#"MailAccounts.AccountName"];
NSLog(#"Account: %#", [item objectAtIndex:2]);
Which essentially returns the email address of the user (we also read some other information on other plist files) so we can add it to the About dialog.
I need now to read this information from the same plist files using C, not Objective-C. The files are not text, they are binary encoded plist files. Is there any way to read those property files from C?
Can I call NSDictionary etc from C? How?
Thanks for the help.
Of course you realize that Objective C is an extension of C, but in general, when I'm using plain ol' C, I use Core Foundation functions and objects instead of Objective C methods.
To your specific question: CFDictionary is toll-free bridged to NSDictionary and CFBundle to NSBundle. You can easily call CoreFoundation from plain ol' C.
You can get what you want with something like:
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFDictionaryRef dictionaryRef = CFBundleGetInfoDictionary(mainBundle);
if(dictionaryRef)
{
CFArrayRef accountsItemsArrayRef = CFDictionaryGetValue(dictionaryRef, CFSTR("MailAccounts.AccountName");
if(accountsItemsArrayRef)
{
CFStringRef accountNameRef = (CFStringRef) CFArrayGetValueAtIndex(accountsItemsArrayRef, 2);
if(accountNameRef)
{
fprintf(stderr, "Account: %s", accountName.cStr());
}
}
}
I just typed this Core Foundation translation directly into this answer box and did no error or sanity checking, which you absolutely would need to do.
Here is a slightly older tutorial that explains a bit more.
Hope this helps to get you on the right path!
Related
I am trying to use C library source files inside my Cocoa Framework which has function named
void swe_set_ephe_path(char *path);
Which will basically be
swe_set_ephe_path(”C:\\SWEPH\\EPHE”);
for windows.
This library contains other data files which only work after this function is set.
When imported to Swift the function looks like this
swe_set_ephe_path(path: UnsafeMutablePointer<Int8!>)
Since i want to bundle up all the data files in framework and use it in my application, i have done something like this
public class SwissEphemeris {
public init() {
let path = Bundle.main.bundlePath
let swePath = UnsafeMutablePointer<Int8>(mutating: (path as NSString).utf8String)
swe_set_ephe_path(swePath)
}
}
But it seems it's not working and the functions which needs data to be searched in files are not able to operate.
If anybody interested to look into Swiss library documentation, check here for the link,
https://www.astro.com/swisseph/swephprg.htm#_Toc505244836
There are two problems:
First, the resource files are in the “Resources” subdirectory of the framework, not in the top-level framework directory. You can obtain a path to that directory with
let resourcePath = Bundle(identifier: "com.Abhi.SwissFramework")!.resourcePath!
or with
let resourcePath = Bundle(for: type(of: self)).resourcePath!
I suggest to force-unwrap the optionals because you know that the bundle and the resources directory exist. A failure would indicate a build problem which should be detected early.
Second, the C function takes a char * argument even though it does not mutate the passed string. Here you can use the approach from UnsafeMutablePointer<Int8> from String in Swift:
resourcePath.withCString {
swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}
Even better: use the dedicated method withUnsafeFileSystemRepresentation() to get the file system representation of the resource path as a C string:
let resourceURL = Bundle(for: type(of: self)).resourceURL!
resourceURL.withUnsafeFileSystemRepresentation {
swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}
I'm learning Swift, and I can see Dictionary in it.
But there are lots of examples that are using NSDictionary with Swift.
What's the difference between these two?
I want to use an array with index in Swift like an array in PHP.
Which one is better to use?
Dictionary is a native Swift struct. NSDictionary is a Cocoa class. They are bridged to one another (within the usual limits), as the docs explain very clearly and fully.
It's exactly parallel to Array and NSArray.
In practice and with regard to Swift's strong type concept the significant difference is
NSDictionary is generally type unspecified
Dictionary is supposed to have a specific type.
Hence native Dictionary is preferable.
Here's the deal,
For all intents and purposes, they are the same thing. So long as you import Foundation, the compiler will know them as the same thing.
As for specific differences, thus Apple doc helps.
Overview
NSObject is the root class of most Objective-C class hierarchies. Through NSObject, objects inherit a basic interface to the runtime system and the ability to behave as Objective-C objects.
What that means, in a nutshell, is that NSObjects are ancient relics from olden (objective c) times.
As for what is better, that is up to you. I find swift objects better than the ns counterpart just for the purpose of keeping code modern, however you may have to use ns objects if you are using code like NSURLCONNECTION that requires ns objects.
Hope this helps.
Consider this example
let dataArray = NSMutableArray()
let d0 = ["code":"AA","name":"American Airlines"]
let d1 = ["code":"BA","name":"British Airlines"]
let d2 = ["code":"DA","name":"Delta Airlines"]
dataArray.addObject(d0)
dataArray.addObject(d1)
dataArray.addObject(d2)
later...
let d0 = dataArray.objectAtIndex(0) as! [String:String]
let lbl = UILabel()
lbl.text = d0["code"] // no xcode warnings
Using NSDictionary in swift
let d0 = dataArray.objectAtIndex(0) as! NSDictionary
Now you need to coerce the dictionary value into shape.
lbl1.text = d0["name"] as! String
From experience - when dealing with json responses - I've used NSDictionary as it's loosely typed and I can't guaranteed to know exactly what it contains - just that is valid json. There's a growing library of native swift tools to handle this use case, I suggest looking here
https://github.com/search?q=json+NSDictionary+swift&type=Code&utf8=%E2%9C%93
In this case - you need to hack around data with the 'if let' dance.
if let results = json["result"] as? NSDictionary
lastly - NSMutableDictionary is more on par with Dictionary as you won't be able to mutate the key / value pairs on a NSDictionary.
eg.
results["code"] = 100 // <-- BOOM
the work around -
let mResults = NSMutableDictionary(dictionary:results)
mResults["code"] = NSNumber(100) // <-- OK
which begs the clarification - you can only stick NSObjects (NSNumbers / NSArrays / NSCount/NSSet) inside the NSMutableDictionaries. The Swift Dictionary gets around this.
I'm new to the site and probably even newer to app development, however i'm learning slowly.. lol
So i hit my first big snag, I've researched all over on the web and can't find what I'm looking for, so here we go.
I'm creating an app that calls upon some user inputted files that can and do change on occasion. I've added the UIFileSharing option for this so users can upload files via iTunes.
There are 3 different types of files that will need to be used, a .opt, a .pkg, and a .txt.
Is there some way i can take the files from the directory, read them, and based off the file extension pull them and use them in a UIPickerView wheel? I'm really new at this so please forgive me when i ask you to be specific.
My assumption is to do this in a few steps, first read the files and sort them and place them in an array based on the extension, then use said array to populate the picker, and also to get the count for number of rows etc..
I guess the second two parts are pretty simple to figure out, just setting up a picker to use an array, i just need to know if its possible to build that array based on the user loaded files.
thanks in advance,
Chuck
You'll need to use the UIDocumentInteractionController class.
Simple Example
UIDocumentInteractionController * controller;
NSURL *fileURL=[NSURL fileURLWithPath:[self getFilePath]]
controller = [ UIDocumentInteractionController interactionControllerWithURL: fileURL ];
// How to get File From the Document Directory
-(NSString *)getFilePath{
NSString *documentPath= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
return [documentPath stringByAppendingPathComponent:#"Your file name"]
}
I solved it guys, thanks for all the help.. Code is below, for anyone interested. Don't forget to define your arrays!
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *bundleDirectory = [fileManager contentsOfDirectoryAtPath:documentsPath error:nil];
NSPredicate *Option = [NSPredicate predicateWithFormat:#"self ENDSWITH '.opt'"];
_OptionArray = [bundleDirectory filteredArrayUsingPredicate:Option];
_OptionPickerData = [_OptionArray copy];
I am building a framework for my day-to-day tasks. I am programming in scala using a lot of type parameter.
Now my goal is to save datastructures to files (e.g. xml files). But I realized that it is not possible using xml files. As I am new to this kind of problem I am asking:
Is there a way to store the types of my datastructures in a file??? Is there a way in scala???
Okay guys. You did a great job basicly by naming the thing I searched for.
Its serialization.
With this in mind I searched the web and was completly astonished by this feature of java.
Now I do something like:
object Serialize {
def write[A](o: A): Array[Byte] = {
val ba = new java.io.ByteArrayOutputStream(512)
val out = new java.io.ObjectOutputStream(ba)
out.writeObject(o)
out.close()
ba.toByteArray()
}
def read[A](buffer: Array[Byte]): A = {
val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(buffer))
in.readObject().asInstanceOf[A]
}
}
The resulting Byte-Arrays can be written to a file and everthing works well.
And I am totaly fine that this solution is not human readable. If my mind changes someday. There are JSON-parser allover the web.
I have been attempting to use NSMutableArray's writeToFile:atomically:
But it has been pointed out to me that this approach is wrong: i.e. iPhone / Objective-C: NSMutableArray writeToFile won't write to file. Always returns NO
It looks like I'm going to have to read the guide on archiving that is referred to in one of the answers in the above link.
Would anyone care to share (or point me towards) some code that helps me accomplish this task?
The method, you've mentioned recursively validates that all the contained objects are property list objects before writing out the file.
Try this:
for (UIImage *image in arrayWithImages) {
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"Documents/%#", #"nameOfTheImage.png"]];
UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
}
Maybe you can use [UIImageJPEGRepresentation(image, 1.0) writeToFile:jpgPath atomically:YES]; to write image as jpeg.