Fixing "Use of undeclared identifier 'NSPreferencePanesDirectory'" - objective-c

My application uses the following code:
#if MAC_OS_X_VERSION_10_5 < MAC_OS_X_VERSION_MAX_ALLOWED
NSArray *globalPreferencePanes =
NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory,
NSAllDomainsMask, YES);
#else
NSArray *globalPreferencePanes =
[NSArray arrayWithObjects:#"/Library/PreferencePanes",
[#"~/Library/PreferencePanes" stringByExpandingTildeInPath], nil];
#endif
return globalPreferencePanes;
The project under which I'm compiling this is aimed at the 10.5 Mac OSX SDK, where NSPreferencePanesDirectory does not exist (it only exists in 10.6+). Because of this, I have the #if and #else in order to check what version of Mac OSX we're running under, so I know whether I should use the NSPreferencePanesDirectory or just manually give the location of the preference pane directories.
What should I change in order to stop getting this "use of undeclared identifier" error?
Thanks.

#if is evaluated at compile time, not run time. What you probably want to do is use the current SDK (10.7), and do something like this:
NSArray *globalPreferencePanes;
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_6)
globalPreferencePanes = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSAllDomainsMask, YES);
else
globalPreferencePanes = [NSArray arrayWithObjects:#"/Library/PreferencePanes", [#"~/Library/PreferencePanes" stringByExpandingTildeInPath], nil];
return globalPreferencePanes;
Making sure to set your target OS version to 10.5 so the symbol is weak linked. Otherwise, you could drop down and use CoreServices' FSFindFolder():
NSMutableArray *globalPreferencePanes = [NSMutableArray array];
FSRef foundRef;
OSErr err = FSFindFolder(kLocalDomain, kPreferencePanesFolderType, false, &foundRef);
if (err != noErr) {
CFURLRef url = CFURLCreateFromFSRef(NULL, &fsRef);
CFStringRef path = CFURLCopyPath(url);
[globalPreferencePanes addObject:(id)path];
CFRelease(path);
CFRelease(url);
}
OSErr err = FSFindFolder(kUserDomain, kPreferencePanesFolderType, false, &foundRef);
if (err != noErr) {
CFURLRef url = CFURLCreateFromFSRef(NULL, &fsRef);
CFStringRef path = CFURLCopyPath(url);
[globalPreferencePanes addObject:(id)path];
CFRelease(path);
CFRelease(url);
}
return globalPreferencePanes;
(Not tested)

If you are using 10.5.x you will still get an error since "NSPreferencePanesDirectory" is not a known symbol. I solved this issue for a friend and changed the FindPrefsDir function code in osxsupport.m to:
char *FindPrefsDir(void)
{
char *resstr = NULL;
NSArray *globalPreferencePanes;
globalPreferencePanes = [NSArray arrayWithObjects:#"/Library/PreferencePanes", [#"~/Library/PreferencePanes" stringByExpandingTildeInPath], nil];
if ([globalPreferencePanes count] > 0)
{
resstr = StringToChar([globalPreferencePanes objectAtIndex:0]) ;
}
return resstr;
}
Thanks to Wevah for his code suggestion, but it didn't directly work for me. So I changed it a little bit and my friend who is still on 10.5.x could perfectly build it after that.

Related

Cocoa/Objective-C get a HFS path (path:to:desktop) from a posix path (path/to/desktop)

I am on OSX, Objective-C.
I have a path/NSURL like
/Users/xxx/Desktop/image2.png
But i pass it to a third party application that excpects finder pathes like
Harddisk:Users:Desktop:image2.png
Is there any method (i can't find) to convert pathes like that or get them out of an NSURL (if possible without string modifying)?
In AppleScript it is
return POSIX file "/Users/xxx/Desktop/image2.png" --> Harddisk:Users:xxx:Desktop:image2.png
EDIT: This is pretty much the same: Cocoa path string conversion
Unfortunately, the method is deprecated...
There is no (easy) alternative at the moment.
The function CFURLCopyFileSystemPath is not deprecated, only the enum case kCFURLHFSPathStyle is deprecated but the raw value 1 is still working and avoids the warning.
I'm using this category of NSString
#implementation NSString (POSIX_HFS)
- (NSString *)hfsPathFromPOSIXPath
{
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)[NSURL fileURLWithPath:self], 1);
return (NSString *)CFBridgingRelease(hfsPath);
}
#end
The function works also in Swift. The Swift version is a bit more sophisticated and adds the trailing semicolon representing a dictionary implicitly, here as an extension of URL:
extension URL {
func hfsPath() -> String?
{
if let cfpathHFS = CFURLCopyFileSystemPath(self as CFURL, CFURLPathStyle(rawValue: 1)!) { // CFURLPathStyle.CFURLHFSPathStyle)
let pathHFS = cfpathHFS as String
do {
let info = try self.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey])
let isDirectory = info.isDirectory!
let isPackage = info.isPackage!
if isDirectory && !isPackage {
return pathHFS + ":" // directory, not package
}
} catch _ {}
return pathHFS
}
return nil
}
}
Vadians answer is better than this one - but if vadians method is deprecated, this will be an alternative. Idea is to use applescripts methods to get HFS path called easily with an osascript from an NSString category.
NSString category (credits: https://stackoverflow.com/a/19014463/4591992)
#implementation NSString (ShellExecution)
- (NSString*)runAsCommand {
NSPipe* pipe = [NSPipe pipe];
NSTask* task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
[task setArguments:#[#"-c", [NSString stringWithFormat:#"%#", self]]];
[task setStandardOutput:pipe];
NSFileHandle* file = [pipe fileHandleForReading];
[task launch];
NSString* result = [[NSString alloc] initWithData:[file readDataToEndOfFile] encoding:NSUTF8StringEncoding];
return result;
}
#end
Usage for this case:
NSString* posixToHFS = [NSString stringWithFormat:#"osascript -e 'POSIX file \"%#\" as text'",filePath];
filePath = [posixToHFS runAsCommand];
In my own testing (on 10.13.6, 10.14.6 and 10.15b7), #vadian's solution doesn't work with paths where a folder name component contains a "/" (when viewed in Finder), which then appears as a ":" in a POSIX path and as a "/" in a HFS path.
Demonstration of the bug
Here's a quick test program that you can build by creating a new "command line" project in Xcode:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *posixPath = #"/EndsInSlash:";
NSURL *url = [NSURL fileURLWithPath:posixPath];
if (url == nil) {
NSLog(#"Oops, this went wrong");
} else {
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)url, 1);
NSString *res = (NSString *)CFBridgingRelease (hfsPath);
NSLog(#"HFS path: <%#>", res);
}
}
return 0;
}
When you run it, you'll probably see a correct result printed, i.e. a path that ends in "/". However, that only works if the folder does not exist. So, create a folder named "EndsInSlash/" (not a file!) in your root folder and run the app again - now the resulting path does not end in "/" any more as it should.
Work-around
Below is a "smart" function that uses the faster CFURLCopyFileSystemPath() function whenever possible, i.e. unless a ":" appears in the POSIX path - in which case it performs the conversion on its own, by splitting up the POSIX path into its components, converting them individually (replacing ":" into "/"), prepending the volume name and then merging the components again. This appears to work fine even on macOS 10.15 (Catalina), despite the deprecation warnings.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
static NSString* stringWithHFSUniStr255(const HFSUniStr255* hfsString)
{
CFStringRef stringRef = FSCreateStringFromHFSUniStr(nil, hfsString);
NSString* result = CFBridgingRelease(stringRef);
return result;
}
NSString* hfsPathFromPOSIXPath (NSString *posixPath)
{
if (posixPath == nil) return #"";
if ([posixPath containsString:#":"]) {
// slow version, but can handle ":" appearing in path components
NSString *result = nil;
FSRef ref;
Boolean isDir;
if (FSPathMakeRef ((const UInt8*)posixPath.UTF8String, &ref, &isDir) == noErr) {
HFSUniStr255 elemName;
FSCatalogInfo catInfo;
NSMutableArray<NSString*> *elems = [NSMutableArray arrayWithCapacity:16];
while (FSGetCatalogInfo (&ref, kFSCatInfoNodeID, &catInfo, &elemName, nil, &ref) == noErr) {
[elems insertObject: stringWithHFSUniStr255(&elemName) atIndex:0];
if (catInfo.nodeID == 2) break;
}
result = [elems componentsJoinedByString:#":"];
}
return result;
} else {
// see https://stackoverflow.com/a/45085776/43615
NSURL *url = [NSURL fileURLWithPath:posixPath];
if (url == nil) {
// could not convert because the path doesn't exist
return nil;
}
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLHFSPathStyle);
return (NSString *)CFBridgingRelease (hfsPath);
}
}
#pragma clang diagnostic pop
See also
Discussion of a related bug with AppleScript, with a work-around: https://forum.latenightsw.com/t/xxx/2097
Bug report filed with Apple: http://www.openradar.me/radar?id=4994410022436864

Persisting bookmark in core-data

I have an OSX application that is supposed to have a list of files from anywhere in the user's disk.
The first version of the app saves the path to these files in a core-data model.
However, if the file is moved or renamed, the tool loses its purpose and the app can crash.
So I decided to use bookmarks. It seems to be working, but every time I try to recover the data, I get the old path of the files. Why is that? What am I missing?
My core-data entity uses a binary data field to persist the bookmark.
The bookmark itself is done like this:
NSData * bookmark = [filePath bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
includingResourceValuesForKeys:NULL
relativeToURL:NULL
error:NULL];
And on loading the application, I have a loop to iterate all the table and recover the bookmark like this:
while (object = [rowEnumerator nextObject]) {
NSError * error = noErr;
NSURL * bookmark = [NSURL URLByResolvingBookmarkData:[object fileBookmark]
options:NSURLBookmarkResolutionWithoutUI
relativeToURL:NULL
bookmarkDataIsStale:NO
error:&error];
if (error != noErr)
DDLogCError(#"%#", [error description]);
DDLogCInfo(#"File Path: %#", [bookmark fileReferenceURL]);
}
If I rename the file, the path is null. I see no difference between storing this NSData object and a string with the path. So I am obviously missing something.
Edit:
I also often get an error like this: CFURLSetTemporaryResourcePropertyForKey failed because it was passed this URL which has no scheme.
I appreciate any help, thanks!
I can't find any issues in my code, so I changed it.
After looking for the reason of the "no scheme" message, I came to the conclusion some third-party application is required for this code to work, and that's undesirable.
I am now using aliases. This is how I create them:
FSRef fsFile, fsOriginal;
AliasHandle aliasHandle;
NSString * fileOriginalPath = [[filePath absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
OSStatus status = FSPathMakeRef((unsigned char*)[fileOriginalPath cStringUsingEncoding: NSUTF8StringEncoding], &fsOriginal, NULL);
status = FSPathMakeRef((unsigned char*)[fileOriginalPath cStringUsingEncoding: NSUTF8StringEncoding], &fsFile, NULL);
OSErr err = FSNewAlias(&fsOriginal, &fsFile, &aliasHandle);
NSData * aliasData = [NSData dataWithBytes: *aliasHandle length: GetAliasSize(aliasHandle)];
And now I recover the path like this:
while (object = [rowEnumerator nextObject]) {
NSData * aliasData = [object fileBookmark];
NSUInteger aliasLen = [aliasData length];
if (aliasLen > 0) {
FSRef fsFile, fsOriginal;
AliasHandle aliasHandle;
OSErr err = PtrToHand([aliasData bytes], (Handle*)&aliasHandle, aliasLen);
Boolean changed;
err = FSResolveAlias(&fsOriginal, aliasHandle, &fsFile, &changed);
if (err == noErr) {
char pathC[2*1024];
OSStatus status = FSRefMakePath(&fsFile, (UInt8*) &pathC, sizeof(pathC));
NSAssert(status == 0, #"FSRefMakePath failed");
NSLog(#"%#", [NSString stringWithCString: pathC encoding: NSUTF8StringEncoding]);
} else {
NSLog(#"The file disappeared!");
}
} else {
NSLog(#"CardCollectionUserDefault was zero length");
}
}
However, I am still curious on why my previous code failed. I appreciate any thoughts on that. Thanks!

CGDisplayIOServicePort is deprecated in OS X >= 10.9, how to replace?

I did small app to allow quickly change screen resolutions on multiple monitors. I want to show product name as title of the monitor, and it's very simple to find using this code:
NSDictionary *deviceInfo = (__bridge NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dispID), kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
if([localizedNames count] > 0) {
_title = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
} else {
_title = #"Unknown display";
}
But CGDisplayIOServicePort is deprecated in OS X >= 10.9 and Apple's documentation says there is no replacement. How to find service port or product name without using this method?
I tried to iterate through IO-registry and tried to use IOServiceGetMatchingServices method to find display services but I'm not very familiar with IO-registry so I couldn't find solution.
Thanks for help!
It looks like #Eun's post missed a piece of information to close this discussion. With a little search, I found that IOServicePortFromCGDisplayID is not an API which Apple provides. Rather, it's a piece of open source code found here:
https://github.com/glfw/glfw/blob/e0a6772e5e4c672179fc69a90bcda3369792ed1f/src/cocoa_monitor.m
I copied IOServicePortFromCGDisplayID and also 'getDisplayName' from it.
I needed two tweaks to make it work on OS X 10.10.
Remove the code to handle serial number in IOServicePortFromCGDisplayID. (CFDictionaryGetValue for
kDisplaySerialNumber returns NULL for me.)
Remove project specific
error handling code in getDisplayName.
If you need more information
Issue tracker of the problem: github.com/glfw/glfw/issues/165
Commit
for the solution:
github.com/glfw/glfw/commit/e0a6772e5e4c672179fc69a90bcda3369792ed1f
I would thank Matthew Henry who submitted the code there.
Here is my take on the issue. I also started with the code from GLFW 3.1, file cocoa_monitor.m.
But I had to modify it in different ways than Hiroshi said, so here goes:
// Get the name of the specified display
- (NSString*) screenNameForDisplay: (NSNumber*) screen_id
{
CGDirectDisplayID displayID = [screen_id unsignedIntValue];
io_service_t serv = [self IOServicePortFromCGDisplayID: displayID];
if (serv == 0)
return #"unknown";
CFDictionaryRef info = IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName);
IOObjectRelease(serv);
CFStringRef display_name;
CFDictionaryRef names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
if ( !names ||
!CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), (const void**) & display_name) )
{
// This may happen if a desktop Mac is running headless
CFRelease( info );
return #"unknown";
}
NSString * displayname = [NSString stringWithString: (__bridge NSString *) display_name];
CFRelease(info);
return displayname;
}
// Returns the io_service_t (an int) corresponding to a CG display ID, or 0 on failure.
// The io_service_t should be released with IOObjectRelease when not needed.
- (io_service_t) IOServicePortFromCGDisplayID: (CGDirectDisplayID) displayID
{
io_iterator_t iter;
io_service_t serv, servicePort = 0;
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect");
// releases matching for us
kern_return_t err = IOServiceGetMatchingServices( kIOMasterPortDefault, matching, & iter );
if ( err )
return 0;
while ( (serv = IOIteratorNext(iter)) != 0 )
{
CFDictionaryRef displayInfo;
CFNumberRef vendorIDRef;
CFNumberRef productIDRef;
CFNumberRef serialNumberRef;
displayInfo = IODisplayCreateInfoDictionary( serv, kIODisplayOnlyPreferredName );
Boolean success;
success = CFDictionaryGetValueIfPresent( displayInfo, CFSTR(kDisplayVendorID), (const void**) & vendorIDRef );
success &= CFDictionaryGetValueIfPresent( displayInfo, CFSTR(kDisplayProductID), (const void**) & productIDRef );
if ( !success )
{
CFRelease(displayInfo);
continue;
}
SInt32 vendorID;
CFNumberGetValue( vendorIDRef, kCFNumberSInt32Type, &vendorID );
SInt32 productID;
CFNumberGetValue( productIDRef, kCFNumberSInt32Type, &productID );
// If a serial number is found, use it.
// Otherwise serial number will be nil (= 0) which will match with the output of 'CGDisplaySerialNumber'
SInt32 serialNumber = 0;
if ( CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplaySerialNumber), (const void**) & serialNumberRef) )
{
CFNumberGetValue( serialNumberRef, kCFNumberSInt32Type, &serialNumber );
}
// If the vendor and product id along with the serial don't match
// then we are not looking at the correct monitor.
// NOTE: The serial number is important in cases where two monitors
// are the exact same.
if( CGDisplayVendorNumber(displayID) != vendorID ||
CGDisplayModelNumber(displayID) != productID ||
CGDisplaySerialNumber(displayID) != serialNumber )
{
CFRelease(displayInfo);
continue;
}
servicePort = serv;
CFRelease(displayInfo);
break;
}
IOObjectRelease(iter);
return servicePort;
}
This works fine for me in a screensaver I wrote under macOS 10.11 (El Capitan).
I tested it with the built-in display of my MacBookPro and an Apple Display connected via Thunderbolt.
As of macOS 10.15 -[NSScreen localizedName] is available:
NSLog(#"Name of main display is %#", NSScreen.mainScreen.localizedName);
NSString* screenNameForDisplay(CGDirectDisplayID displayID)
{
NSString *screenName = nil;
io_service_t service = IOServicePortFromCGDisplayID(displayID);
if (service)
{
NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
if ([localizedNames count] > 0) {
screenName = [[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] retain];
}
[deviceInfo release];
}
return [screenName autorelease];
}

Get a list of unmountable drives using Cocoa

I would like to obtain a list of drives that are unmountable/ejectable using Cocoa/Objective-C under OS X.
I was hoping that NSWorkspace getFileSystemInfoForPath::::: would help me:
NSArray* listOfMedia = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths];
NSLog(#"%#", listOfMedia);
for (NSString* volumePath in listOfMedia)
{
BOOL isRemovable = NO;
BOOL isWritable = NO;
BOOL isUnmountable = NO;
NSString* description = [NSString string];
NSString* type = [NSString string];
BOOL result = [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:volumePath
isRemovable:&isRemovable
isWritable:&isWritable
isUnmountable:&isUnmountable
description:&description
type:&type];
NSLog(#"Result:%i Volume: %#, Removable:%i, W:%i, Unmountable:%i, Desc:%#, type:%#", result, volumePath, isRemovable, isWritable, isUnmountable, description, type);
}
Output:
...
Result:1 Volume: /Volumes/LR Photos, Removable:0, W:1, Unmountable:0, Desc:hfs, type:hfs
...
"LR Photos" is an external drive (connected via Thunderbolt) that should be removable and/or unmountable (or, at least I think it should be). :)
Should I be going about this a different way?
Thanks in advance!
You can use diskArbitration framework.
#import <DiskArbitration/DiskArbitration.h>
+(NSMutableArray *)getListOfEjectableMedia
{
NSArray *mountedRemovableMedia = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
NSMutableArray *result = [NSMutableArray array];
for(NSURL *volURL in mountedRemovableMedia)
{
int err = 0;
DADiskRef disk;
DASessionRef session;
CFDictionaryRef descDict;
session = DASessionCreate(NULL);
if (session == NULL) {
err = EINVAL;
}
if (err == 0) {
disk = DADiskCreateFromVolumePath(NULL,session,(CFURLRef)volURL);
if (session == NULL) {
err = EINVAL;
}
}
if (err == 0) {
descDict = DADiskCopyDescription(disk);
if (descDict == NULL) {
err = EINVAL;
}
}
if (err == 0) {
CFTypeRef mediaEjectableKey = CFDictionaryGetValue(descDict,kDADiskDescriptionMediaEjectableKey);
CFTypeRef deviceProtocolName = CFDictionaryGetValue(descDict,kDADiskDescriptionDeviceProtocolKey);
if (mediaEjectableKey != NULL)
{
BOOL op = CFEqual(mediaEjectableKey, CFSTR("0")) || CFEqual(deviceProtocolName, CFSTR("USB"));
if (op) {
[result addObject:volURL];
}
}
}
if (descDict != NULL) {
CFRelease(descDict);
}
if (disk != NULL) {
CFRelease(disk);
}
if (session != NULL) {
CFRelease(session);
}
}
return result;
}
Unfortunately getFileSystemInfoForPath: is not really the right way to do this. What removable means is that the volume is on removable media such as a CD or DVD. In practice unmountable seems to give the same results as removable. See for example, this post on results using getFileSystemInfoForPath. So unless you want to simply know if a volume is on removable media, you'll need to use another technique.
What you really want to check is the connection bus type of the volume. Firewire, USB, Thunderbolt, etc. are unmountable in the sense you mean. You can see this information in Disk Utility if you select the volume and push the "Info" button under "Connection Bus". Getting this information programmatically is much harder and as far as I can tell is only possible using the IOKit. Details are in Apple's documentation on Accessing Hardware from Applications.
you can use command line version of Disk Utility app that is "diskutil", run it with parameter "list" and pipe output and get it in your program ( don't need to use cocoa ).

List / Scan for available WiFis iPhone

I'm searching for a way to present available WiFis in an iPhone App.
So far my research resulted in the following:
Apps that implement(ed) such a functionality were removed from the AppStore (means you can't deploy the App via AppStore which is fine for me)
Apple hides the functionality that is necessary for a scan in a private framework and you can't find any explanations/comments/examples on "how to use"
http://code.google.com/p/iphone-wireless seems to be most promising. anyway, i can't figure out how to include the delivered sources in my code so that it runs on a device
Even the adaptions that are mentioned htt ://code.google.com/p/iphone-wireless/issues/detail?id=26 didn't get me the desired results. The most progress was ending up with a
dlopen error: dlopen(/System/Library/SystemConfiguration/Aeropuerto.bundle/Aeropuerto, 1): image not found
failed: __Apple80211Associate
message after launching the app on a device (iPhone 3GS; iOS 3.1.3).
Used source code that procudes the error is here:
NSMutableDictionary *networks;
bool scanning;
void *libHandle;
void *airportHandle;
int (*open)(void *);
int (*bind)(void *, NSString *);
int (*close)(void *);
int (*scan)(void *, NSArray **, void *);
networks = [[NSMutableDictionary alloc] init];
// libHandle = dlopen("/System/Library/Frameworks/Preferences.framework/Preferences", RTLD_LAZY);
// libHandle = dlopen("/System/Library/PrivateFrameworks/Apple80211.framework/Preferences", RTLD_LAZY);
libHandle = dlopen("/System/Library/SystemConfiguration/WiFiManager.bundle/WiFiManager", RTLD_LAZY);
open = dlsym(libHandle, "Apple80211Open");
bind = dlsym(libHandle, "Apple80211BindToInterface");
close = dlsym(libHandle, "Apple80211Close");
scan = dlsym(libHandle, "Apple80211Scan");
open(&airportHandle);
bind(airportHandle, #"en0");
NSLog(#"Scanning...");
scanning = true;
NSArray *scan_networks;
NSDictionary *parameters = [[NSDictionary alloc] init];
scan(airportHandle, &scan_networks, parameters);
bool changed;
for (int i = 0; i < [scan_networks count]; i++) {
if([networks objectForKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]] != nil
&& ![[networks objectForKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]] isEqualToDictionary:[scan_networks objectAtIndex: i]])
changed = true;
[networks setObject:[scan_networks objectAtIndex: i] forKey:[[scan_networks objectAtIndex: i] objectForKey:#"BSSID"]];
}
if(changed) {
NSLog(#"NetworksUpdated");
}
scanning = false;
NSLog(#"Scan Finished...");
NSLog(#"Found %i networks: %#", [networks count], networks);
Even if trying one of the other commented lines, it doesn't work:
program received EXC_BAD_ACCESS and several
warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.
What i'm searching are hints how to include iphone-wireless in my project and how to modify the given code?
An alternative would be a tip on how to scan for WiFis in your environment.
Would be nice if someone could help.
path has changed in 3.X and beyond, from :
/System/Library/SystemConfiguration/Aeropuerto.bundle/Aeropuerto
to:
/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfifuration