Xamarin iOS binding Library compilation issue - xamarin

We are creating an iOS binding library for an objective C static lib.
The following property is causing a compilation error. We have created the ApiDefinition files using Objective sharpie
Error BI1078: bgen: Do not know how to make a signature for System.Byte* in method `get_DataY' (BI1078)
// #required #property (readonly, nonatomic) const uint8_t * _Nonnull dataY;
[Abstract]
[Export("dataY")]
unsafe byte* DataY { get; }
What do we replace byte* with?

Related

How can I get the a certificate's validity period using Apple's Security framework?

I am parsing certificates inside macOS app's code signature and I want to get the expiration date (aka "validity period"). According to Apple's documentation the certificate contains a validity period but there is no function mentioned for retrieving it.
I am currently manually digging into the certificate and grabbing the value manually using SecCertificateCopyValues() from the dictionary but this does not seem to be the proper approach.
How can I get a SecCertificateRef's validity period (NSDate) in CoreFoundation or Foundation (Objective-C) using Apple's Security framework (not OpenSSL)?
Thank you.
For those who are interested in my approach I'll leave my snippet here. Cheers!
#import <Foundation/Foundation.h>
id getX509ValueforKey(SecCertificateRef certificate, CFStringRef kSecPropertyKey) {
id value;
CFDictionaryRef valuesDict = SecCertificateCopyValues(certificate, (__bridge CFArrayRef)#[(__bridge id)kSecPropertyKey], NULL);
if (valuesDict) {
CFDictionaryRef invalidityDateDictionaryRef = CFDictionaryGetValue(valuesDict, kSecPropertyKey);
if (invalidityDateDictionaryRef) {
CFTypeRef invalidityRef = CFDictionaryGetValue(invalidityDateDictionaryRef, kSecPropertyKeyValue);
if (invalidityRef)
value = CFBridgingRelease(invalidityRef);
}
CFRelease(valuesDict);
}
return value;
}
int main(int argc, const char * argv[]) {
SecCertificateRef certificateRef = NULL;
NSDate *certExpiryDate = getX509ValueforKey(certificateRef, kSecOIDInvalidityDate);
NSLog(#"certExpiryDate: %#", certExpiryDate);
return noErr;
}

Xamarin.iOS UIApperance setDefaultTextAttributes

I'm trying to figure out how to implement following code in Xamarin:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:#{NSForegroundColorAttributeName:[UIColor greenColor]}];
But I cannot find a way to setDefaultTextAttributes on UIApperance class.
There are a number of missing UIAppearance features in Xamarin.iOS and in regards to your question, there is a missing API.
This is a bug, šŸ£ I wrote my own UIAppearance.cs to add the missing features and correct the missing API and assume no other Xamarin.iOS coders really use the newer UIAppearance features as it has been broken since iOS 9 in Xamarin.
First, appearanceWhenContainedIn is deprecated and you should be using appearanceWhenContainedInInstancesOfClasses instead.
AppearanceWhenContainedIn - was deprecated in iOS 9 and is not recommended for use.
Second, appearanceWhenContainedInInstancesOfClasses is incorrectly defined within Xamarin.iOS as only available in tvOS and that is just not true.
#if TVOS
// new in iOS9 but the only option for tvOS
const string selAppearanceWhenContainedInInstancesOfClasses = "appearanceWhenContainedInInstancesOfClasses:";
~~~
UIAppearance.cs#L77
Update: I submitted a Github issue regarding this.
https://github.com/xamarin/xamarin-macios/issues/3230
Thus it is not available via the Xamarin.iOS wrapper API, but of course is available directly from the ObjC runtime as such:
var NSForegroundColorAttributeName = Dlfcn.GetStringConstant(UIKitLibraryHandle, "NSForegroundColorAttributeName");
var defaultAttributes = NSDictionary.FromObjectsAndKeys(new NSObject[] { UIColor.Red }, new NSObject[] { NSForegroundColorAttributeName });
var styleHandle = GetAppearanceEx(Class.GetHandle("UITextField"), typeof(UISearchBar));
void_objc_msgSend_IntPtr(styleHandle, Selector.GetHandle("setDefaultTextAttributes:"), defaultAttributes.Handle);
The next problem there are a number of Xamarin.iOS methods marked internal that are needed for the above code to function, so some copy/paste/modify of some source is needed:
public const string selAppearanceWhenContainedInInstancesOfClasses = "appearanceWhenContainedInInstancesOfClasses:";
public static readonly IntPtr UIKitLibraryHandle = Dlfcn.dlopen("/System/Library/Frameworks/UIKit.framework/UIKit", 0);
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public static extern IntPtr IntPtr_objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1);
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public static extern void void_objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1);
public static IntPtr GetAppearanceEx(IntPtr class_ptr, params Type[] whenFoundIn)
{
var ptrs = TypesToPointers(whenFoundIn);
var handles = NSArray.FromIntPtrs(ptrs);
using (var array = handles)
{
return IntPtr_objc_msgSend_IntPtr(class_ptr, Selector.GetHandle(selAppearanceWhenContainedInInstancesOfClasses), array.Handle);
}
}
public static IntPtr[] TypesToPointers(Type[] whenFoundIn)
{
IntPtr[] ptrs = new IntPtr[whenFoundIn.Length];
for (int i = 0; i < whenFoundIn.Length; i++)
{
if (whenFoundIn[i] == null)
throw new ArgumentException(String.Format("Parameter {0} was null, must specify a valid type", i));
if (!typeof(NSObject).IsAssignableFrom(whenFoundIn[i]))
throw new ArgumentException(String.Format("Type {0} does not derive from NSObject", whenFoundIn[i]));
var classHandle = Class.GetHandle(whenFoundIn[i]);
if (classHandle == IntPtr.Zero)
throw new ArgumentException(string.Format("Could not find the Objective-C class for {0}", whenFoundIn[i].FullName));
ptrs[i] = classHandle;
}
return ptrs;
}

Warn"use of undeclared identifier self" when use c function

this is my code in ViewController.h in CoCoa to implement "CFsocket"
#interface ViewController : NSViewController
-(IBAction)start:(id)sender;
#property (strong, nonatomic) IBOutlet NSTextView *CommandDisplay;
this is ViewController.m
#implementation ViewController
#synthesize CommandDisplay=_CommandDisplay;
void AcceptCallBack(CFSocketRef socket,CFSocketCallBackType type,CFDataRef address,const void *data,void *info)
{
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
// For a kCFSocketConnectCallBack that failed in the background, it is a pointer to an SInt32 error code; for a kCFSocketAcceptCallBack, it is a pointer to a CFSocketNativeHandle; or for a kCFSocketDataCallBack, it is a CFData object containing the incoming data. In all other cases, it is NULL.
CFSocketNativeHandle sock = *(CFSocketNativeHandle *) data;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock, &readStream, &writeStream);
if (!readStream || !writeStream)
{
close(sock);
NSLog(#"CFStreamCreatePairWithSocket()Fail");
return;
}
CFStreamClientContext streamCtxt = {0, NULL, NULL, NULL, NULL};
CFReadStreamSetClient(readStream, kCFStreamEventHasBytesAvailable, ReadStreamClientCallBack, &streamCtxt);
CFWriteStreamSetClient(writeStream, kCFStreamEventCanAcceptBytes, WriteStreamClientCallBack, &streamCtxt);
CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);
CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
}
// readstream operatoion , use when client transmitted data
void ReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void* clientCallBackInfo)
{
UInt8 buff[255];
CFReadStreamRef inputStream = stream;
CFReadStreamRead(stream, buff, 255);
_CommandDisplay.string=[self._CommandDisplay.string stringByAppendingString:[NSString stringWithFormat:#"SeverCreat failed\n"]];
NSLog(#"receiveļ¼š %s",buff);
NSLog(#"%#",clientCallBackInfo);
CFReadStreamClose(inputStream);
CFReadStreamUnscheduleFromRunLoop(inputStream,CFRunLoopGetCurrent(),kCFRunLoopCommonModes);
inputStream = NULL;
}
when i use c function , it can't recognize _CommandDisplay which i have synthesize ,but i need to print read data to NSTextView,how can i solve this problem?
In Objective-C a synthesized property foo is backed by an implicit instance variable _foo.
If you want to access the instance variable directly use _foo without self.
If you want to access the property by its synthesized getter and setter use self.foo (without the underscore)
Write
self.CommandDisplay.string = [self.CommandDisplay.string stringByAppendingString:#"SeverCreat failed\n"];
or
_CommandDisplay.string = [_CommandDisplay.string stringByAppendingString:#"SeverCreat failed\n"];
NSString stringWithFormat is not needed, there are no format parameters, and you can also delete the #synthesize line, it's not needed either.
A small side-note:
If the C-function was outside the scope of the implementation block, you would have to pass the reference to the NSTextView instance thru the info parameter of the function, but in this case it should work

Wifi Scanner for iOS8

How do i find out the Wifi signal strengths(RSSI) in iOS8 ?
I know that Apple restricts apps from accessing the Wi-Fi data/API directly and will not be accepted in AppStore. I found a private API called Stumbler which is supposed to be doing the same. Here is the link to it. Accessing & Using the MobileWiFi.framework
networks = [[NSMutableDictionary alloc] init];
void* library = dlopen("/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfiguration", RTLD_LAZY);
int (*apple80211Open)(void*) = (int(*)(void*))dlsym(library, "Apple80211Open");
int (*apple80211Bind)(void*, NSString*) = (int(*)(void*, NSString*))dlsym(library, "Apple80211BindToInterface");
apple80211Close = (int(*)(void*))dlsym(library, "Apple80211Close");
apple80211Scan= (int(*)(void*, NSArray**, void*))dlsym(library, "Apple80211Scan");
void *airport = NULL;
apple80211Open(&airport);
apple80211Bind(airport, #"en0");
NSArray* arrNetworks = nil;
apple80211Scan(airport, &arrNetworks, (__bridge void *)(networks));
//"networks" is an array of NSDictionary objects for all the visible Wi-Fi networks
apple80211Close(airport);
dlclose(library);
Somehow this is not working in iOS8. Anyone has any idea how to get this working?? Thanks for the help !!

How to show simple text messages (toasts/alerts) in a Cocoa MacOS Webview?

I've already searched "everything" about this in Google/Stackoverflow, but I'm still stuck. I have just started developing OSX Apps, so I'm a (almost) complete newbie in Objective-C and Xcode 5 (5.0.2).
All I need is a simple webview to load a webgame from a given URL. This webview must behave just like a very simple Safari browser. My app is already working relatively well. It loads the game OK, and after a lot of struggling I succeeded making it show javascript alerts and confirms.
THE POINT: I need to display a simple text message to the user, in case of no internet connection is detected, then I need to close the app. It seems a very trivial thing, but I can't find a way to do that!!
That's my appDelegate.M:
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize myWebView;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
// Check if there's internet connection:
#include <SystemConfiguration/SystemConfiguration.h>
static BOOL internetOk()
{
BOOL returnValue = NO;
struct sockaddr zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sa_len = sizeof(zeroAddress);
zeroAddress.sa_family = AF_INET;
SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithAddress(NULL, (const struct sockaddr*)&zeroAddress);
if (reachabilityRef != NULL)
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
BOOL connectionRequired = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
returnValue = (isReachable && !connectionRequired) ? YES : NO;
}
CFRelease(reachabilityRef);
}
return returnValue;
}
// -
if(internetOk())
{
[self.window setContentView:self.myWebView];
[self.window toggleFullScreen:#""];
[self.myWebView setMainFrameURL:#"http://www.mywebgameurl.com"];
}
else
{
// SHOWS ERROR MESSAGE AND CLOSES APP! HOW CAN I DO IT????
}
}
#end
Any help is welcome, thanks!!
You're looking for the NSAlert class, check here for Apple's docs.
Sample usage:
NSAlert* alert = [NSAlert alertWithMessageText:#"Internet Error"
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:#"No internet."];
[alert runModal];

Resources