How to make "SBAwayController * controller = [objc_getClass("SBAwayController") sharedAwayController]" working? - frameworks

I want to check whether the screen is locked with private api.
And I get some code from google:
#import <SpringBoard/SpringBoard.h>
#import <SpringBoard/SBAwayController.h>
Class clsAway = objc_allocateClassPair(clsAlert, "SBAwayController", 0);
objc_registerClassPair(clsAway);
Class clsAwayController = objc_getClass("SBAwayController");
SBAwayController * controller = [clsAwayController sharedAwayController];
if ([controller isLocked]){
NSLog(#"double check Home ,now YES Lock");
}
else{
NSLog(#"double check Home ,now NO Lock");
}
To make these code to work, I download the private headers from kennytm's github and import SpringBoard.h and SBAwayController.h
Compile ok and run it on my iPhone 4S, it seems that I can get a non-nil pointer with objc_getClass("SBAwayController");
But the program crashed at line:
SBAwayController * controller = [clsAwayController sharedAwayController];
with an error: '+[SBAwayController sharedAwayController]: unrecognized selector sent to class 0x1456c0'
Any other works do I need to make these code to work?
I know that the usage of private api can cause the rejection from Apple, but I just want to know how to make it work. Thanks for any suggestions!

SBAwayController WAS NOT REMOVED IN iOS 5. How can you expect to use a SpringBoard method from another process? SpringBoard is NOT a framework. It's an executable.

I believe SBAwayController was removed in the iOS 5. I checked SpringBoard and it has only reminiscences of this class.

Victor is wrong. The class is still present in iOS 6
cy# c = SBAwayController.sharedAwayController;
#"<SBAwayController: 0x1c510580> <SBActivationContext: 0x1c50be50> activate: deactivate: "
cy# printMethods(SBAwayController);
[{selector:#selector(hasEverBeenLocked),implementation:0x109c49},{selector:#selector(activateLostModeForRemoteLock:),implementation:0x116505},{selector:#selector(unlockWithSound:),implementation:0x110835},{selector:#selector(frontLocked:animate:automatically:),implementation:0x1120d5},{selector:#selector(cancelDimTimer),implementation:0x11291d},{selector:#selector(activeAwayPluginController),implementation:0x116885},{selector:#selector(shouldShowInCallUI),implementation:0x116111
...

Related

Facebook SDK for Xamarin.iOS login return issue

I'm trying to use the Facebook SDK for Xamarin.iOS(the one from Facebook, not from Octorcurve) to get the users Authed on my app.
I've followed the Sample that comes with the component from the store. The sample just works but I'm stuck after the login/permissions without firing the events to notify the viewController that we have a user logged in. I have set the plist file with the app name, id, and Url schema as requested by facebook SDK. So, the code is:
Note that I'm not creating the UI from code. I have a .xib IB file with the UI and yes, I added a view for the FBLoginView and set its custom class to FBLoginView.
AppDelegate.cs(omitted the rest of code for brevity):
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
viewController = new LoginViewController ();
navController = new UINavigationController (viewController);
window.RootViewController = navController;
window.MakeKeyAndVisible ();
return true;
}
public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return FBSession.ActiveSession.HandleOpenURL(url);
}
public override void OnActivated (UIApplication application)
{
FBSession.ActiveSession.HandleDidBecomeActive();
}
LoginViewController.cs(the controller for the NIB file):
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
loginView = btnLogin as FBLoginView;
loginView.ReadPermissions = new string[] { "email" };
loginView.PublishPermissions = new string[]{ "publish_actions", "publish_stream", "manage_pages" };
loginView.DefaultAudience = FBSessionDefaultAudience.Everyone;
loginView.ShowingLoggedInUser += (sender, e) =>
{
var a = e;
};
loginView.FetchedUserInfo += (sender, e) =>
{
user = e.User;
};
}
So, whis this code I have 2 issues:
Note that I'm casting btnLogin as FBLoginView since idk how to set the outlet on Interface Builder to use the right type of FBLoginView... It always say that it its type wasnt found when I'm adding the Outlet in the .h file. So I just created it as UIView and did the cast on the code. This cast is valid and still working, since the permissions that I'm passing are being asked for user authorisation at the consent FB screen.
The two events ShowingLoggedInUser and FetchedUserInfo never get called and the AppDelegate never call OpenUrl neither OnActivated.
Am I missing something? All I need is get the access_token that should be returned somewhere after the login. How do I get it?
I really appreciate any help.
Thanks!
Just to provide feedback for people...
Suddenly, after 2 days hitting my head agains the wall, I just cleaned the project, rebuild it and restarted Xamarin STUDIO... Now the events are fired... No single thing changed and things are working...
There are weird behaviours unexplained to me with Xamarin that just work or not, like sometime I start the app, and it just hangs on "Waiting for debugger to connect..." and nothing happens connecting to the device while in Simulator it works fine...
Thanks

iPhone unit testing for viewController

I have a controller class in which i want to write the test case for the code which executed on the button click .In my testClass.m file i have following code from which i want to call the button from testClass.m . will this code work??
-(void)testcheckTheArrayForNull
{
viewController.temp=#"c";
viewController.buttonCount=1;
[viewController goButton:self];
STAssertNotNil(viewController.setUpArray,#"set up Array is not nil");
}
By this code will my control transfer to goButton???
I would say this could work, but you didn't provide code for goButton, setUpArray and I have no idea what temp or buttonCount do - so just guessing.

what dows TTIsPad() do in Xcode using Three20?

i'm using Three20 in XCode but i copied a piece of code like this:
if (TTIsPad()) {
SplitCatalogController* controller =
(SplitCatalogController*)[[TTNavigator navigator] viewControllerForURL:#"tt://catalog"];
SplitCatalogController* controller =
(SplitCatalogController*)[[TTNavigator navigator] viewControllerForURL:#"tt://catalog"];
TTDASSERT([controller isKindOfClass:[SplitCatalogController class]]);
map = controller.rightNavigator.URLMap;
}
But i don't know what does the function TTIsPad do, please help me.
It is a convenience method that returns true if the current device is an iPad, and false otherwise.
The source can be found here. It first checks whether the device is running iOS 3.2 or greater. If not, it returns false (iPads shipped with 3.2) If it is greater than 3.2, it returns the result of (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) which is true only if the device is an iPad.

iAd Crashing in 3.2

I'm noticing my iAd is causing a crash on iOS 3.2. I am weak linking in the build settings. It crashes in my createAdBanner method
NSString *contentSize;
if (&ADBannerContentSizeIdentifierPortrait != nil) {
contentSize = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? ADBannerContentSizeIdentifierPortrait : ADBannerContentSizeIdentifierLandscape;
}
else {
contentSize = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? ADBannerContentSizeIdentifier320x50 : ADBannerContentSizeIdentifier480x32;
}
Here is the error that comes up.
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 4681.
Assertion failed: (cls), function getName, file /SourceCache/objc4_Sim/objc4-427.1.1/runtime/objc-runtime-new.m, line 3939.
Assertion failed: (cls), function getName, file /SourceCache/objc4_Sim/objc4-427.1.1/runtime/objc-runtime-new.m, line 3939.
Current language: auto; currently objective-c
(gdb)
I thought you were able to run iAds on 3.2 if you weak linked. Any ideas or suggestions?
http://developer.apple.com/library/ios/#documentation/userexperience/Reference/ADBannerView_Ref/Reference/Reference.html
ADBannerView is available in 4.0 or later.
You won't be able to show ads in 3.2
Aside from weak-linking, you must check if the ad classes are available on the device. To do so, you can use the following to test for the existence of a class:
Class adClass = NSClassFromString(#"AdBannerView");
if(adClass){
//ads are available so optionally show them
}else{
// ads are not available
}
To check for a particular method, you would use this:
BOOL methodExists = [someObject respondsToSelector:#selector(selectorToTestName:)];
if(methodExists){
//Safe to call selector
}else{
//The selector doesn't exist in this version of iOS.
}
You could also just use the above statement, "inlining" the boolean check:
if([someObject respondsToSelector:#selector(selectorToTestName:)]){
//Safe to call selector
}else{
//The selector doesn't exist in this version of iOS.
}
ADBannerViewcan be used in 4.0 and above. See the apple documentation
use below link it is giving more clearly even to use in ios 3.0+ IAD Tutorial you have to import _weak_framework iAd in the linkingFlags wich is available in the targets.Once go through the link.

How to call Objective-C from Javascript?

I have a WebView, and I want to call a view in Objective-C from JavaScript. Does someone know how I can do this?
I have this code in my ViewController:
- (BOOL)webView:(UIWebView *)webView2
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:#":"];
if ([components count] > 1 &&
[(NSString *)[components objectAtIndex:0] isEqualToString:#"myapp"]) {
if([(NSString *)[components objectAtIndex:1] isEqualToString:#"myfunction"])
{
NSLog([components objectAtIndex:2]); [[Airship shared] displayStoreFront]; //<- This is the code to open the Store
NSLog([components objectAtIndex:3]); // param2
// Call your method in Objective-C method using the above...
}
return NO;
}
return YES; // Return YES to make sure regular navigation works as expected.
}
And in Javascript:
function store(event)
{
document.location = "myapp:" + "myfunction:" + param1 + ":" + param2;
}
But nothing happens.
The standard workaround for UIWebView is to set a UIWebViewDelegate, and implement the method webView:shouldStartLoadWithRequest:navigationType:. In your JavaScript code, navigate to some fake URL that encodes the information you want to pass to your app, like, say:
window.location = "fake://myApp/something_happened:param1:param2:param3";
In your delegate method, look for these fake URLs, extract the information you need, take whatever action is appropriate, and return NO to cancel the navigation. It's probably best if you defer any lengthy processing using some flavor of performSelector.
The window.location method of calling objective c from JS isn't recommended. One example of problems: if you make two immediate consecutive calls one is ignored (since you can't change location too quickly) - try it yourself..
I recommend the following alternative approach:
function execute(url)
{
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", url);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
You call the execute function repeatedly and since each call executes in its own iframe, they should not be ignored when called quickly.
Credits to this guy.
Obliviux,
Your code seems to be perfect.
The reason for the problem is that you must have missed to map the delegate.
Either
Connect the delegate of the webView to the file owner in the .xib file
or
Use webView.delegate = self;
in your viewDidLoad.
Thanks
Like people said here, you have to use the method webView:shouldStartLoadWithRequest:navigationType: from the UIWebviewDelegate.
This api http://code.google.com/p/jsbridge-to-cocoa/ does it for you. It is very lightweight. You can pass images, strings and arrays from javascript to objective-C.
I had an issue with this approach: I wanted to send several messages to the iphone device, but it seemed that they were "overlaped" as they could not process all of them sequentially.
Example: when executing this code:
window.location = "app://action/foo";
window.location = "app://action/bar";
The action foo was never executed.
What I had to do was the following:
waitingForMessage = false;
function MsgProcessed(){
waitingForMessage = false;
}
function SyncLaunchURL(url){
if (waitingForMessage){
setTimeout(function(){SyncLaunchURL(url)},100);
}else{
window.location = url
waitingForMessage = true;
}
}
SyncLaunchURL("app://action/foo");
SyncLaunchURL("app://action/bar");
With this approach, the iphone has to call MsgProcessed() after processing the call. This way works for me, and maybe helps someone with the same problem!
Assuming you're doing an app, you can look at how PhoneGap implements that (or even use it). It's a library that supports back-and-forth communication between JS and OBJ-C. There are other libraries and solutions, as well.
If you're talking about a web app (something the user gets to from Mobile Safari), you can't get to Objective-C from there.
Check this one - understanding XMLHttpRequest responses using this (or other javascript) functions?, it's using objective C to call ajax js function, and get the response after it's done, you know the trick is that webview will be triggered when you change the location in javascript, so you can check the location to know its your javascript call or the real request.
Although this is a very old question now, it keeps getting returned by Google and there is a good answer now: the WebScripting informal protocol. It allows you to expose an objective C object to Javascript.
http://developer.apple.com/library/safari/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html#//apple_ref/doc/uid/30001215-BBCBFJCD