ios - how to call the ShareKit share from an action button - ios

I am working from this example of setting up ShareKit: http://getsharekit.com/install/
and their example has this:
- (void)myButtonHandlerAction
{
// Create the item to share (in this example, a url)
NSURL *url = [NSURL URLWithString:#"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:#"ShareKit is Awesome!"];
// Get the ShareKit action sheet
SHKActionSheet *actionSheet = [SHKActionSheet actionSheetForItem:item];
// Display the action sheet
[actionSheet showFromToolbar:navigationController.toolbar];
}
But the last line there gives me a syntax error:
Use of undeclared identifier 'navigationController'
Also, my function is defined like this because I was looking to invoke the Sharing library after the user pressed the share button:
- (IBAction)share:(id)sender
Would anyone know why I am getting this error and what would be the right way to invoke the share functionality in my case?
Thanks!

Without seeing your entire code, it sounds like you don't have a UINavigationController, just a UIViewController. If that's the case, this should do the trick.
In you .h file
#property (nonatomic, strong) IBOutlet UIWindow *window;
#property (nonatomic, strong) UINavigationController *NVC;
In your .m file
UIViewController *theViewController = [[TheViewController alloc]initWithNibName:#"TheViewController" bundle:nil];
self.NVC = [[UINavigationController alloc] initWithRootViewController:theViewController];
[[self window] setRootViewController:NVC];
[self.window makeKeyAndVisible];

Related

Why does this code cause a memory leak?

I execute this code in my applicationDidBecomeActive callback.
- (void)applicationDidBecomeActive:(UIApplication *)application{
[self showMainWindow];
}
- (void) showMainWindow{
PushNotificationTabBarController *pushNotificationTabBarController = [[PushNotificationTabBarController alloc] initWithNibName:#"PushNotificationTabBarController" bundle:nil];
self.viewDeckController.centerController =
pushNotificationTabBarController; // registered for Notification via addObserver...
}
The setter is defined like this:
#property (nonatomic, strong) IBOutlet UIViewController* centerController;
IIViewDeckController property in my AppDelegate:
#property (strong, nonatomic) IIViewDeckController *viewDeckController;
I found out that I have 2 PushNotificationTabBarController objects when I close and re-enter the app, with no reference to one of them, like a memory leak. However I dont understand why this code is causing it because to me it seems ok. I'm using ARC.
Before setting pushNotificationTabBarController check for self.viewDeckController.centerController object. If it exists, release and assigned to nil and assign new object of 'pushNotificationTabBarController'
id controller = self.viewDeckController.centerController;
if (controller) {
[controller release];
controller = nil;
}
self.viewDeckController.centerController = pushNotificationTabBarController;

Unable to load new URL to UIWebView from another controller

I am new to iOS and I'm trying to make an webview-based app with sidebar drawer and simple navigation (I'm using MFSideMenu library). I'm able to load URL with my webview:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIWebViewDelegate>{
UIWebView *webView;
}
#property (retain, nonatomic) IBOutlet UIWebView *webView;
- (IBAction)showLeftMenuPressed:(id)sender;
- (void) loadURL;
#property (nonatomic, strong) NSURL *url;
#end
ViewController.m
#import "ViewController.h"
#import "MFSideMenu.h"
#interface ViewController ()
- (void)webViewDidFinishLoad:(UIWebView *)webView;
#end
#implementation ViewController
#synthesize webView;
#synthesize url;
- (void)viewDidLoad
{
[super viewDidLoad];
webView.delegate=self;
if(self.url == Nil) {
NSString *myURL = #"http://google.com/";
self.url = [NSURL URLWithString:myURL];
}
[self loadURL];
}
-(void)loadURL{
NSLog(#"loadURL: %#", self.url);
[self.webView loadRequest:[NSURLRequest requestWithURL:self.url]];
}
When I'm trying to load new URL using following code, I'm receiving right url param value. Another controller is a sidebar (drawer) tableview where I'm selecting an item to change the URL showing in the main view (ViewController which contains webview).
Another controller:
ViewController *webViewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
NSString *urlString = #"http://kirk.kh.ua/";
NSString *encodedString=[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:encodedString];
webViewController.url = url;
//[self.navigationController pushViewController:webViewController animated:YES];
[webViewController loadURL];
[webViewController release];
You may notice that there is a commented line - I have tried this solution, but result is the same: when I'm calling code in another controller nothing happens with the ViewController's webview which is strange because in log output I see that loadURL method was called and it gives me a right URL (kirk.kh.ua).
UPD: I have noticed that on the first load webview as an object, and then it appears to be null (see log):
UPD2: I have noticed that webivew object and other synthesized objects are null when I'm calling them from another class, but this objects exist and accessible when I'm logging them from self (ViewController) controller.
Can anyone suggest how can I access ViewController class objects from another class?
Instead of trying to open the URL from the Another Controller - make a NSString property in the ViewController, then when you tap a cell just pass the URL as a string:
ViewController *webViewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
webViewController.urlString = #"http://kirk.kh.ua/";
And then add in the ViewController add something like this in the viewWillAppear:
if (![self.urlString isEqualToString:#""]) {
NSString *encodedString=[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:encodedString];
webViewController.url = url;
[webViewController loadURL];
}

xctest - how to test if a new view loads on a button press

Just started xcode 5 and xctest. How do I test that a view loads on button press. I have programatically added method that gets called when the rightBarButtonItem is clicked
action:#selector(onSettingsButton)
and in onSettingsButton
-(void) onSettingsButton{
SettingsViewController *svc = [[SettingsViewController alloc] init];
[self.navigationController pushViewController:svc animated:YES];
}
How to write xctest to ensure SettingsViewController brings up the Settings view? Thank you.
You need an interaction test — that is, a test that checks interactions between objects. In this case, you want to test that -pushViewController:animated: is called on the navigation controller with a SettingsViewController. So we want to put a mock object into self.navigationController which we can ask, "Were you called as expected?"
I'll assume a simple name for the class: MyView.
The way I'd do this by hand is to Subclass and Override navigationController. So in my test code, I'd do something like this:
#interface TestableMyView : MyView
#property (nonatomic, strong) id mockNavigationController;
#end
#implementation TestableMyView
- (UINavigationController *)navigationController
{
return mockNavigationController;
}
#end
Now instead of creating a MyView, the test will create a TestableMyView and set its mockNavigationController property.
This mock can be anything, as long as it responds to -pushViewController:animated: and records the arguments. Here's a simple example, by hand:
#interface MockNavigationController : NSObject
#property (nonatomic) int pushViewControllerCount;
#property (nonatomic, strong) UIViewController *pushedViewController;
#property (nonatomic) BOOL wasPushViewControllerAnimated;
#end
#implementation MockNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
self.pushViewControllerCount += 1;
self.pushedViewController = viewController;
self.wasPushViewControllerAnimated = animated;
}
#end
Finally, here's a test:
- (void)testOnSettingsButton_ShouldPushSettingsViewController
{
// given
MockNavigationController *mockNav = [[MockNavigationController alloc] init];
TestableMyView *sut = [[TestableMyView alloc] init];
sut.mockNavigationController = mockNav;
// when
[sut onSettingsButton];
// then
XCTAssertEquals(1, mockNav.pushViewControllerCount);
XCTAssertTrue([mockNav.pushedViewController isKindOfClass:[SettingsViewController class]]);
}
These things can be simplified by using mock object frameworks such as OCMock, OCMockito, or Kiwi's mocking. But I think it helps to start by hand first, so that you understand the concepts. Then choose the tools that help. And if you know how to do it by hand, you'll never say, "Mocking framework X doesn't do what I need! I'm stuck!"
Found one way. Maybe there are others ..
- (void)testSettingsViewShowsWhenSettingsButtonIsClicked{
[self.tipViewController onSettingsButton];
id temp = self.tipViewController.navigationController.visibleViewController;
XCTAssertEqual([temp class], [SettingsViewController class], #"Current controller should be Settings view controller");
}
First call the onSettingsButton, which is the same as clicking the button, but not really. Maybe it's okay for this simple test case? How to simulate the actual press?
Then get the current view from the tipviewcontoller which is the rootview of the app and check that it is a SettingsViewController.

passing a value to a button in xcode

I am seeing if there is a way to pass a variable to a button in xcode. I have a web link that I am retrieving from an API that I am storing to a NSString. I am just wondering if there is a way to pass that to a button so that when it is clicked it can follow the link accordingly.
You store that URL lcoally in some ivar or property. You assign an action to your button as usual. The action is nothing less than a method of your view controller. Within that method you execute that link.
This is how you can "follow" your link:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.klecker.de"]];
In your case you would use an NSString variable instead of the constant that I am using in this example.
You can just subclass the UIBUtton and add any properties/variables that you like/need. From your description I would use a NSURL instead of NSString...
Create a new UIButton subclass, in your .h file write:
#import <UIKit/UIKit.h>
#interface MyButton : UIButton
{
NSURL* buttonUrl;
}
#property (nonatomic, retain) NSURL* buttonUrl;
#end
and in the .m file simply:
#import "MyButton.h"
#implementation MyButton
#synthesize buttonUrl;
#end
Then in your ViewController: (don't forget to #import "MyButton.h)
MyButton *theButton = [[MyButton alloc] initWithFrame:someframe];
[theButton addTarget:self action:#selector(buttonPushed:) forControlEvents:UIControlEventTouchUpInside];
theButton.buttonUrl = [NSURL URLWithString:apiString];
[self.view addSubView:theButton];
[theButton release];
... And then you can get the URL again when the button was pushed as:
-(void)buttonPushed:(id)sender{
NSURL* theUrl = [(MyButton*)sender getButtonUrl];
}

UIButton deallocated issue

I received this message from the debugger console :
-[UIButton release]: message sent to deallocated instance 0x1836b0
But I don't create UIButton programmatically, all my buttons have created in Interface Builder. Each of them are linked to a function, like this :
-(IBAction)theFunction:(UIButton *)sender;
In lot of this functions, I don't use the variable sender. I don't even try to release it. So I don't understand why my application try to release my buttons.
Do I do something in Interface Builder to release or not my UIButton? Is it about the picture I put in the UIButton? If I use the variable (UIButton *)sender, do I need to release it?
This problem stucks me because of it my application crashes.
Edit:
- (IBAction)showPopoverOverview:(UIButton *)sender {
TouchPlanePopover *content = [[TouchPlanePopover alloc] init];
[content setTheAlbum:#"Overview"];
// Setup the popover for use in the detail view.
detailViewPopover = [[UIPopoverController alloc] initWithContentViewController:content];
detailViewPopover.popoverContentSize = CGSizeMake(600., 400.);
detailViewPopover.delegate = self; // Set the sender to a UIButton.
// Present the popover from the button that was tapped in the detail view.
[detailViewPopover presentPopoverFromRect:sender.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// Set the last button tapped to the current button that was tapped.
lastTappedButton = sender;
[content release];
}
detailViewPopover is create in .h like this : #property (nonatomic, retain) UIPopoverController *detailViewPopover;
Thans for your help
Let me know if you need more information, I will edit the post
Change
-(IBAction)theFunction:(UIButton *)sender
to
-(IBAction)theFunction:(id)sender
Just try...
I am working on this and its work properly
So may be its useful for you.
myController.h
#import <\UIKit/UIKit.h>
#class myController;
#interface myController : UIViewController {
}
- (IBAction)onButtonClick:(UIButton *)button;
#end
myController.m
#implementation myController
- (IBAction)onButtonClick:(UIButton *)button {
NSLog(#"work properly");
}

Resources