Im currently developing a videostreaming iOS App with the MobileVLCKit framework. To navigate through the different transmitters I use the UISplitViewController. The App works fine until I lock the screen of the iPad 3. I Debugged the code and know that the player is still running in the background. I have to access the media player property (_mediaplayer) to stop the player if it gets resign or enters background in app deligate.
I have searched in the www and on stackoverflow, but it seems to be a little part that i might not see or misunderstand. I would be very pleased if someone could take a minute and help me spot the problem.
btw. Yeah my first post on SO, after nearly two years of using it :D
Question: How can I access the property in the appDeligate.m?
AppDeligate.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UISplitViewController *splitViewController;
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) DetailViewController *viewController;
#end
AppDeligate.m
#import "AppDelegate.h"
#import "DetailViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
DetailViewController *thePlayer = [[splitViewController viewControllers] objectAtIndex:1];
if(thePlayer._mediaplayer.isPlaying == true) {
NSLog(#"Player is playing");
}
NSLog(#"Background");
}
DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController <UISplitViewControllerDelegate>
#property (strong, nonatomic) VLCMediaPlayer* _mediaplayer;
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UIView *movieView;
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#property (strong, nonatomic) UIPopoverController *masterPopoverController;
#end
#implementation DetailViewController
#synthesize _mediaplayer;
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
NSLog(#"setDetailItem");
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)mediaPlayerStateChanged:(NSNotification *)aNotification
{
VLCMediaPlayerState currentState = _mediaplayer.state;
/* Playback opening */
if (currentState == VLCMediaPlayerStateOpening) {
[self.indicator startAnimating];
NSLog(#"Openning");
}
/* or if playback ended */
if (currentState == VLCMediaPlayerStateEnded || currentState == VLCMediaPlayerStateStopped) {
NSLog(#"Stopped");
[self.indicator stopAnimating];
}
/* Playback buffering */
if (currentState == VLCMediaPlayerStateBuffering) {
NSLog(#"buffering");
[self.indicator startAnimating];
}
/* Playback buffering */
if (currentState == VLCMediaPlayerStatePlaying) {
NSLog(#"Playing");
[self.indicator stopAnimating];
}
}
- (void)configureView
{
NSLog(#"configureView");
// Update the user interface for the detail item.
if (self.detailItem) {
self.imageView.image = nil;
if(self._mediaplayer.isPlaying) {
// Stop active media
[self._mediaplayer stop];
}
// Set new url
self._mediaplayer.media = [VLCMedia mediaWithURL:[NSURL URLWithString:_detailItem]];
// Play new media
[self._mediaplayer play];
// Set radio image
if ([_detailItem rangeOfString:#"239.192.1"].location != NSNotFound) {
[self.imageView setImage:[[UIImage imageNamed:#"music.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
self.imageView.contentMode = UIViewContentModeCenter;
}
}
}
- (void)viewDidDisappear
{
NSLog(#"viewDidDisappear");
if (self._mediaplayer) {
#try {
[self._mediaplayer removeObserver:self forKeyPath:#"time"];
[self._mediaplayer removeObserver:self forKeyPath:#"remainingTime"];
}
#catch (NSException *exception) {
NSLog(#"we weren't an observer yet");
}
if (self._mediaplayer.media)
[self._mediaplayer stop];
if (self._mediaplayer)
self._mediaplayer = nil;
}
}
- (void)viewDidLoad
{
NSLog(#"viewDidLoad");
[super viewDidLoad];
// Hide navbar
[[self navigationController] setNavigationBarHidden:YES animated:YES];
// Background logo
[self.imageView setImage:[[UIImage imageNamed:#"background.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
self.imageView.contentMode = UIViewContentModeCenter;
// Init media player
[self initMediaplayer];
}
- (void)initMediaplayer
{
self._mediaplayer = [[VLCMediaPlayer alloc] init];
self._mediaplayer.delegate = self;
self._mediaplayer.drawable = self.movieView;
NSLog(#"Init VLC Player");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Split view
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:
(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
#end
Make splitViewController an instance variable in #interface and than change:
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
DetailViewController *thePlayer = [[splitViewController viewControllers] objectAtIndex:1];
[thePlayer._mediaplayer stop];
NSLog(#"Resign");
}
This is the final code which worked for me. Feel free to use!
AppDelegate.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) DetailViewController *viewController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "DetailViewController.h"
#interface AppDelegate () {
UISplitViewController *splitViewController;
UINavigationController *navigationController;
VLCMedia *currentPlayback;
}
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
splitViewController = (UISplitViewController *)self.window.rootViewController;
navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(#"WillResignActive");
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"DidEnterBackground");
DetailViewController *dvc = (DetailViewController *)navigationController.topViewController;
if (dvc._mediaplayer.isPlaying) {
[dvc._mediaplayer stop];
NSLog(#"Mediaplyer stopped");
currentPlayback = dvc._mediaplayer.media;
NSLog(#"Saved current playback");
while (dvc._mediaplayer.isPlaying) {
[NSThread sleepForTimeInterval:0.1];
}
}
if (dvc._mediaplayer != nil) {
dvc._mediaplayer = nil;
NSLog(#"Set player to nil");
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(#"WillenterForeground");
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(#"DidBecomeActive");
DetailViewController *dvc = (DetailViewController *)navigationController.topViewController;
if (dvc._mediaplayer == nil) {
dvc._mediaplayer = [[VLCMediaPlayer alloc] init];
dvc._mediaplayer.delegate = self;
dvc._mediaplayer.drawable = dvc.movieView;
NSLog(#"init mediaplayer");
}
if (currentPlayback != nil || dvc._mediaplayer.media == nil) {
dvc._mediaplayer.media = currentPlayback;
NSLog(#"set current playback media");
}
if (dvc._mediaplayer.media != nil || dvc._mediaplayer.isPlaying == false) {
[dvc._mediaplayer play];
NSLog(#"play");
}
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#import <MobileVLCKit/MobileVLCKit.h>
#interface DetailViewController : UIViewController <UISplitViewControllerDelegate>
#property (strong, nonatomic) IBOutlet UITapGestureRecognizer *tapGestureRecognizer;
#property (strong, nonatomic) VLCMediaPlayer* _mediaplayer;
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UIView *movieView;
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#property (strong, nonatomic) UIPopoverController *masterPopoverController;
#property (strong, nonatomic) UIBarButtonItem *barButton;
#end
#implementation DetailViewController
#synthesize _mediaplayer;
- (IBAction)handleTap:(UITapGestureRecognizer *)sender {
[_barButton.target performSelector: _barButton.action withObject: _barButton];
}
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
NSLog(#"setDetailItem");
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)mediaPlayerStateChanged:(NSNotification *)aNotification
{
VLCMediaPlayerState currentState = _mediaplayer.state;
/* Playback opening */
if (currentState == VLCMediaPlayerStateOpening) {
[self.indicator startAnimating];
NSLog(#"Openning");
}
/* or if playback ended */
if (currentState == VLCMediaPlayerStateEnded || currentState == VLCMediaPlayerStateStopped) {
NSLog(#"Stopped");
[self.indicator stopAnimating];
}
/* Playback buffering */
if (currentState == VLCMediaPlayerStateBuffering) {
NSLog(#"buffering");
[self.indicator startAnimating];
}
/* Playback buffering */
if (currentState == VLCMediaPlayerStatePlaying) {
NSLog(#"Playing");
[self.indicator stopAnimating];
}
}
- (void)configureView
{
NSLog(#"configureView");
// Update the user interface for the detail item.
if (self.detailItem) {
self.imageView.image = nil;
if(_mediaplayer.isPlaying) {
// Stop active media
[_mediaplayer stop];
}
// Set new url
_mediaplayer.media = [VLCMedia mediaWithURL:[NSURL URLWithString:_detailItem]];
// Play new media
[_mediaplayer play];
// Set radio image
if ([_detailItem rangeOfString:#"239.192.1"].location != NSNotFound) {
[self.imageView setImage:[[UIImage imageNamed:#"music.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
self.imageView.contentMode = UIViewContentModeCenter;
}
}
}
- (void)viewDidLoad
{
NSLog(#"viewDidLoad");
[super viewDidLoad];
// Hide navbar
[[self navigationController] setNavigationBarHidden:YES animated:YES];
// Show navbar
[_barButton.target performSelector: _barButton.action withObject: _barButton afterDelay:1];
// Background logo
[self.imageView setImage:[[UIImage imageNamed:#"background.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
self.imageView.contentMode = UIViewContentModeCenter;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Split view
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:
(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
_barButton = barButtonItem;
}
#end
Related
Sorry about the confusion.
What I want to do:
enter a string in a textfield in a view(EnterCommandViewController) and click save button, which will dismiss current view and go back to another view(DetectionViewController) and show the string in the UILabel in current view(DetectionViewController). So I have put define the delegate protocol in EnterCommandViewController, my question is that why the respondToSelector, which is used to check whether someone is listening does not work.
I am really a beginner in iOS, I am right now writing a delegate to send text got form UITextField to a UILabel, But I found that the respondToSelector cannot be called by using NSLog for testing.
Below is my code for reference:
EnterCommandViewController.h
#import <UIKit/UIKit.h>
#import "RscMgr.h"
#protocol EnterCommandDelegate <NSObject>
-(void) commandEntered:(NSString*)command;
#end
#interface EnterCommandViewController : UIViewController <RscMgrDelegate>
{
RscMgr* rscMgr;
__weak IBOutlet UITextField *inputTextField;
__unsafe_unretained id<EnterCommandDelegate> delegate;
}
-(void)sendMessage:(NSString*)message;
- (IBAction)cancelPressed;
- (IBAction)savePressed;
#property (nonatomic,assign)id delegate;
#end
EnterCommandViewController.m
#import "EnterCommandViewController.h"
#interface EnterCommandViewController () <UITextFieldDelegate>
{
#private
BOOL connected;
}
#end
#implementation EnterCommandViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
rscMgr = [[RscMgr alloc] init];
[rscMgr setDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
inputTextField.text=#"";
[inputTextField becomeFirstResponder];
}
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputTextField.delegate = self;
}
-(void) viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
inputTextField.delegate = nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cancelPressed {
[self dismissViewControllerAnimated:YES completion:^{}];
}
- (IBAction)savePressed {
//is anyone listening
NSLog(#"the command is %#",inputTextField.text);
NSLog(#"Checking -- SomeMethod is listening");
if([delegate respondsToSelector:#selector(commandEntered:)]){
NSLog(#"SomeMethod is listening");
//send delegate function with the command entered by the user
[delegate commandEntered:inputTextField.text];
}
[self dismissViewControllerAnimated:YES completion:^{}];
}
DetectionViewController.h
#import <UIKit/UIKit.h>
#import "EnterCommandViewController.h"
#interface DetectionViewController : UIViewController <EnterCommandDelegate>{
__weak IBOutlet UILabel *showCommand;
}
- (IBAction)showSettings:(UIBarButtonItem *)sender;
#end
DetectionViewController.m
#import <Foundation/Foundation.h>
#import "DetectionViewController.h"
#implementation DetectionViewController
- (IBAction)showSettings:(UIBarButtonItem *)sender {
}
-(void) viewDidLoad{
[super viewDidLoad];
showCommand.text=#"";
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
}
#pragma mark - EnterCommandDelegate function(s)
-(void) commandEntered:(NSString *)command{
// showCommand.text = command;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"command: %#",command);
[self->showCommand setText:command];
});
}
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
You are not setting the delegate properly.
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
This is not the way of setting the delegate in your case, since you are not using the created instance of enterCVC, instead a new instance is created from the storyboard when you are transitioning toEnterCommandViewController `(From your comment its clear that you are using the storyboard for this).
So what you can do is you should the delegate from prepareForSegue in DetectionViewController like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get reference to the destination view controller
EnterCommandViewController* enterCVC = [segue destinationViewController];
enterCVC.delegate = self;
}
So perhaps this is a beginner's mistake and super easy to you guys, but i really do not know how to solve it,really appreciate for any suggestions:
Right Now:
1: I have to ViewController: EnterCommandViewController and DetectionViewController
2: I wrote Delegate protocol in EnterCommandViewController and set DetectionViewController as its delegate.
3: About delegate: I have a inputTextField in the EnterCommandView and a "Save" bar button item on the top toolbar in this view. Once I click the save , current view will be dismissed and return back to DetectionView and show the NSString just entered in the UILabel in DetectionView.
Finally, My question is that Why After I alloc and init a EnterCommandViewController instance , that is enterCVS, the instance is still nil as show in end of my post.
Code:
EnterCommandViewController.h
#import <UIKit/UIKit.h>
#import "RscMgr.h"
#protocol EnterCommandDelegate <NSObject>
#optional
-(void) commandEntered:(NSString*)command;
#end
#interface EnterCommandViewController : UIViewController <RscMgrDelegate,EnterCommandDelegate>
{
RscMgr* rscMgr;
IBOutlet UITextField *inputTextField;
// DetectionViewController* detectionViewController;
// __unsafe_unretained id<EnterCommandDelegate> delegate;
}
-(void)sendMessage:(NSString*)message;
-(id)initWithDelegate:(id)delegateToBe;
- (IBAction)cancelPressed;
- (IBAction)savePressed;
#property (nonatomic,weak) id<EnterCommandDelegate> delegate; //assign replaced
#end
EnterCommandVIewController.m
#import "EnterCommandViewController.h"
#import "DetectionViewController.h"
#interface EnterCommandViewController () <UITextFieldDelegate>
{
#private
BOOL connected;
}
#end
#implementation EnterCommandViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
rscMgr = [[RscMgr alloc] init];
[rscMgr setDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
[inputTextField becomeFirstResponder];
}
-(id)initWithDelegate:(id)delegateToBe{
if(self = [super init]){
delegate = delegateToBe;
}
return self;
}
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputTextField.delegate = self;
}
-(void) viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
inputTextField.delegate = nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITextFieldDelegate Methods
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[self sendMessage:textField.text];
textField.text = nil;
return NO;
}
#pragma mark - Serial Tx/Rx Methods Implementation
-(void) sendMessage:(NSString *)message{
if(connected == YES) {
[rscMgr writeString:message];
}
else{
NSLog(#"CableDisconnected!");
NSLog(#"Attempted To Send: %#",message);
}
}
- (IBAction)cancelPressed {
[self dismissViewControllerAnimated:YES completion:^{}];
}
- (IBAction)savePressed {
//is anyone listening
if([[[UIDevice currentDevice]systemVersion] compare:#"7.0" options:NSNumericSearch] != NSOrderedAscending){
NSLog(#"SYStem version > 7.0");
}
if(delegate&&[delegate respondsToSelector:#selector(commandEntered:)]){
NSLog(#"SomeMethod is listening");
[delegate commandEntered:inputTextField.text];
}
[self dismissViewControllerAnimated:YES completion:nil]; //commened: ^{}
}
#pragma mark - RscMgrDelegate Methods Implementation
-(void) cableConnected:(NSString *)protocol{
inputTextField.text = #"cableConnected";
[rscMgr setBaud:9600];
[rscMgr open];
connected = YES;
}
-(void) cableDisconnected{
inputTextField.text = #"cableDisconnected";
connected = NO;
}
-(void) readBytesAvailable:(UInt32)length{}
-(void) portStatusChanged{}
#end
DetectionViewController.h
#import <UIKit/UIKit.h>
#import "EnterCommandViewController.h"
#interface DetectionViewController : UIViewController <EnterCommandDelegate>{
}
- (IBAction)showSettings:(UIBarButtonItem *)sender;
#property (nonatomic, strong) EnterCommandViewController* enterCVC;
#property (nonatomic, strong) IBOutlet UILabel *showReceivedCommand;
#end
DetectionViewController.m
#import <Foundation/Foundation.h>
#import "DetectionViewController.h"
#import "EnterCommandViewController.h"
#implementation DetectionViewController
#synthesize showReceivedCommand;
#synthesize enterCVC;
- (IBAction)showSettings:(UIBarButtonItem *)sender {
}
-(void) viewDidLoad{
[super viewDidLoad];
if(showReceivedCommand){
showReceivedCommand.text=#"Initial text";
NSLog(#"UILAbel in ViewDidload is not nil");
}else {
NSLog(#"UILAbel in viewDidload is nil");
}
enterCVC = [[EnterCommandViewController alloc] init];
if(enterCVC.delegate) NSLog(#"X nil");
[enterCVC setDelegate:self];
}
#pragma mark - EnterCommandDelegate function(s)
-(void)commandEntered:(NSString *)command{
dispatch_async(dispatch_get_main_queue(), ^{
if(showReceivedCommand){
NSLog(#"UILabel is not nil");
}else{NSLog(#"UILabel is nil");}
showReceivedCommand = [[UILabel alloc] init];
NSLog(#"command received: %#",command);
showReceivedCommand.text = command;
[showReceivedCommand setNeedsDisplay];
NSLog(#"text in showReceivedCommand is %#",showReceivedCommand.text);
});
}
#end
I set a break point at DetectionViewController.n --> ViewDidLoad() --> [enterCVC setDelegate:self];
I got:
self DetectionViewController * 0x15c50e850 0x000000015c50e850
UIViewController UIViewController
showReceivedCommand UILabel * 0x15c510650 0x000000015c510650
enterCVC EnterCommandViewController * 0x15c611360 0x000000015c611360
showReceivedCommand UILabel * 0x15c510650 0x000000015c510650
enterCVC EnterCommandViewController * 0x15c611360 0x000000015c611360
UIViewController UIViewController
rscMgr RscMgr * nil 0x0000000000000000
inputTextField UITextField * nil 0x0000000000000000
connected BOOL NO false
delegate id 0x0 0x0000000000000000
enterCVC = [[EnterCommandViewController alloc] init]
Try changing that to....
enterCVC = [[EnterCommandViewController alloc] initWithDelegate:self];
I haven't found a similar question that could answer my question.
My Question is: Why can't I access a UILabel from another class after the dissmissViewController?
Here is my Code:
ClassA.h:
#interface ClassA : UIViewController {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
ClassA.m:
shouldPerformSegue, prepareForSegue and statusBarStyle Methods
ClassB.h:
- (IBAction)dismiss;
ClassB.m:
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
ClassA *login = [[ClassA alloc] init];
[[login ErrorLabel] setText:#"Please use login."];
[[login acIn1] stopAnimating];
[[login acIn1] setHidesWhenStopped:YES];
[[login acIn1] setHidden:YES];
}];
}
Here is my Code I really hope somebody can help me: I AM ABOUT TO GIVE UP I DON'T KNOW WHY THIS WON'T WORK!
Thanks for your help.
~Markus
Edit1:
I have a ViewController ClassA that contains two text fields and when you click on login you come to a TabBarController where one tab contains the ClassB ViewController and in the ClassB ViewController there is a logout button --> dismiss and when you click this button you should come to the ClassA ViewController AND the ErrorLabel Text should change.
Complete Class: A --> LoginViewControler.h
#import <UIKit/UIKit.h>
#import "ShowProfileViewController.h"
#interface LoginViewController : UIViewController <ShowProfileViewControllerDelegate> {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
#property (weak, nonatomic) IBOutlet UITextField *passwordTextField;
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
#end
Complete Class: A --> LoginViewController.m
#import "LoginViewController.h"
#import "NewsNavigationController.h"
#import "TabViewController.h"
#interface LoginViewController () <UITextFieldDelegate>
#end
#implementation LoginViewController
#synthesize usernameTextField;
#synthesize passwordTextField;
#synthesize ErrorLabel;
#synthesize acIn1;
- (void)viewDidLoad
{
[super viewDidLoad];
[usernameTextField setDelegate:self];
[passwordTextField setDelegate:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if([identifier isEqualToString:#"login"])
{
[acIn1 startAnimating];
[acIn1 setHidden:NO];
if([self login]){
return YES;
} else {
[self showErrorMessage:#"Data not correct!"];
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
return NO;
}
}
else {
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
return NO;
}
}
- (void)showErrorMessage:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
- (BOOL)login
{
NSString *usernameS = usernameTextField.text;
NSString *passwordS = passwordTextField.text;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://localhost:8888/login.php?username=%#&password=%#", usernameS, passwordS]]];
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *loginDic = [jsonDictionary objectForKey:#"login"];
NSString *ErrorString = [loginDic objectForKey:#"returnString"];
NSLog(#"[+] Login: %#", ErrorString);
if ([ErrorString isEqualToString:#"Success"]){
ErrorLabel.text = #"Login";
return YES;
}
else {
ErrorLabel.text = ErrorString;
return NO;
}
}
- (void)didDismissViewController
{
[ErrorLabel setText:#"Bitte benutzen Sie den Login."];
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)inSegue sender:(id)inSender
{
if([inSegue.identifier isEqualToString:#"login"])
{
ShowProfileViewController *vc = [[ShowProfileViewController alloc] init];
vc.delegate = self;
TabViewController *tabViewController = inSegue.destinationViewController;
NewsNavigationController *theController = [[tabViewController viewControllers] objectAtIndex:0];
[self presentViewController:vc animated:YES completion:nil];
}
}
#end
Complete Class: B --> ShowProfileViewController.h
#import <UIKit/UIKit.h>
#protocol ShowProfileViewControllerDelegate
- (void)didDismissViewController;
#end
#interface ShowProfileViewController : UIViewController
#property (nonatomic, assign) id<ShowProfileViewControllerDelegate> delegate;
- (IBAction)dismiss;
#end
Complete Class: B --> ShowProfileViewController.m
#import "ShowProfileViewController.h"
#import "LoginViewController.h"
#interface ShowProfileViewController ()
#end
#implementation ShowProfileViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
- (void)viewWillAppear:(BOOL)inAnimated
{
[super viewWillAppear:inAnimated];
}
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController];
}];
}
#end
This doesn't work because inside your completion block, you're creating a new instance of your LoginViewController, and setting its text. What you should be actually doing is setting the text of the existing LoginViewController, that should appear after dismissing ShowProfileViewController
In order to achieve your desired behaviour, you can use the delegation pattern. If you're not familiar with this technique, it'd be very important to learn. It's is used all over the place in iOS and Mac OS X development.
The code below might require some tweaking on your side.
In ShowProfileViewController.h, add before #interface:
#protocol ShowProfileViewControllerDelegate
- (void)didDismissViewController
#end
Also, add the following property declaration to ShowProfileViewController:
#property (nonatomic, assign) id<ShowProfileViewControllerDelegate> delegate;
Then, change LoginViewController.h so it looks like
#import "ShowProfileViewController.h"
#interface LoginViewController : UIViewController <ShowProfileViewControllerDelegate> {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
Now, in ShowProfileViewController.m, replace the code in the dismiss method so it looks like the following:
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController];
}];
}
In LoginViewController.m, add the following method:
- (void)didDismissViewController
{
[[self ErrorLabel] setText:#"Please use login."];
[[self acIn1] stopAnimating];
[[self acIn1] setHidesWhenStopped:YES];
[[self acIn1] setHidden:YES];
}
And finally, you need to set the delegate property in you ShowProfileViewController to point to the LoginViewController instance. Find in LoginViewController.m in which part of your code you create and present the ShowProfileViewController View Controller and set the delegate property to self. If you're using storyboards, you should do it inside prepareForSegue:.
ClassA *login = [[ClassA alloc] init];
is creating a completly new instance.Not the one you used for coming to class B
i have a tab bar and navigation controller for my app. whenever i tap the scan tab, it kept throwing me Thread 1: EXC_BAD_ACCESS error on line:
ZXCapture.m
[output ZXQT(setDelegate:)ZXAV(setSampleBufferDelegate:)self
Here is my code:
tab bar:
TestScanViewController *scannerViewController=[[TestScanViewController alloc] initWithNibName:#"TestScanViewController" bundle:nil];
navigationController =[[UINavigationController alloc] initWithRootViewController:scannerViewController];
in the TestScanViewController.h:
#interface TestScanViewController : UIViewController <ZXCaptureDelegate>
#end
in the TestScanViewController.m:
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import "TestScanViewController.h"
#interface TestScanViewController ()
#property (nonatomic, strong) ZXCapture* capture;
#property (nonatomic, weak) IBOutlet UILabel* decodedLabel;
#end
#implementation TestScanViewController
#pragma mark - View Controller Methods
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%s",__PRETTY_FUNCTION__);
if (self.capture == nil) {
self.capture = [[ZXCapture alloc] init];
self.capture.delegate = self;
self.capture.rotation = 90.0f;
// Use the back camera
self.capture.camera = self.capture.back;
self.capture.layer.frame = self.view.bounds;;
[self.view.layer addSublayer:self.capture.layer];
[self.view bringSubviewToFront:self.decodedLabel];
}else{
[self.capture start];
[self.view.layer addSublayer:self.capture.layer];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(#"%s",__PRETTY_FUNCTION__);
[self.capture.layer removeFromSuperlayer];
[self.capture stop];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return toInterfaceOrientation == UIInterfaceOrientationPortrait;
}
#pragma mark - Private Methods
- (NSString*)displayForResult:(ZXResult*)result {
}
return [NSString stringWithFormat:#"Scanned!\n\nFormat: %#\n\nContents:\n%#", formatString, result.text];
}
#pragma mark - ZXCaptureDelegate Methods
- (void)captureResult:(ZXCapture*)capture result:(ZXResult*)result {
if (result) {
// We got a result. Display information about the result onscreen.
[self.decodedLabel performSelectorOnMainThread:#selector(setText:) withObject:[self displayForResult:result] waitUntilDone:YES];
// Vibrate
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
- (void)captureSize:(ZXCapture*)capture width:(NSNumber*)width height:(NSNumber*)height {
}
#end
just like the examples codes from github:
https://github.com/TheLevelUp/ZXingObjC/blob/master/examples/BarcodeScanner/ViewController.m
I had the same problem. If you are targeting iOS version 6 or higher and using ARC, then the cause of the problem is an incomplete migration to ARC in ZXCapture.m.
Look around line 56 for this code:
#interface ZXCapture ()
#property (nonatomic, assign) dispatch_queue_t captureQueue;
#end
The assign is a leftover from before ARC days. It also causes a compiler warning, which was my clue to the solution.
To solve the problem, change the code into:
#interface ZXCapture ()
#property (nonatomic, strong) dispatch_queue_t captureQueue;
#end
I'm trying to modify the demo that comes with the Facebook iOS SDK.
I need the login button appears in a second modal view.
When I click on the login button, it opens Facebook App and authorization is sought, then returns to my app but fbDidLogin is not fired.
I have followed all the steps from here https://github.com/facebook/facebook-ios-sdk.
Here is the code i'm using. Please help me to find out what i'm missing.
I'm using Xcode 4.1 and iOS SDK 4.3
myAppAppDelegate.h
#import <UIKit/UIKit.h>
#import "loginView.h"
#import "firstView.h"
#class firstView;
#interface myAppAppDelegate : NSObject <UIApplicationDelegate> {
firstView* controller;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet firstView *firstViewViewController;
#end
myAppAppDelegate.m
#import "firstView.h"
#import "loginView.h"
#synthesize window;
#synthesize firstViewViewController = _ firstViewViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
controller = [[firstView alloc] init];
firstView *firstView = [[firstView alloc] initWithNibName:nil bundle:nil];
[window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [[controller fb] handleOpenURL:url];
}
- (void)dealloc {
[window release];
[_firstViewViewController release];
[controller release];
[super dealloc];
}
#end
firstView.h
#import <UIKit/UIKit.h>
#interface firstView : UIViewController
-(IBAction)openLoginView:(id)sender;
#end
firstView.m
#import "loginView.h"
#implementation firstView
-(IBAction)openLoginView:(id)sender{
loginView *loginView = [[loginView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:loginView animated:YES];
}
#end
loginView.h
#import <UIKit/UIKit.h>
#import "FBConnect.h"
#interface loginView : UIViewController<FBRequestDelegate,
FBDialogDelegate,
FBSessionDelegate>{
NSArray* _permissions;
Facebook* _fb;
}
#property(readonly) Facebook *fb;
-(IBAction)fbButtonClick:(id)sender;
#end
loginView.m
#import "loginView.h"
static NSString* kAppId = #"260718013943480";
#implementation loginView
#synthesize fb = _fb;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (!kAppId) {
NSLog(#"missing app id!");
exit(1);
return nil;
}
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_permissions = [[NSArray arrayWithObjects:
#"read_stream", #"publish_stream", #"offline_access",nil] retain];
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
_fb = [[Facebook alloc] initWithAppId:kAppId];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)login {
[_fb authorize:_permissions delegate:self];
}
- (IBAction)fbButtonClick:(id)sender {
NSLog(#"login button clicked");
[self login];
}
- (void)fbDidLogin {
NSLog(#"logged in");
}
/**
* Called when the user canceled the authorization dialog.
*/
-(void)fbDidNotLogin:(BOOL)cancelled {
NSLog(#"did not login");
}
/**
* Called when the request logout has succeeded.
*/
- (void)fbDidLogout {
NSLog(#"logedout");
}
#end
First of all, how does this even compile?
#synthesize firstViewViewController = _ firstViewViewController;
You don't have _firstViewController declared anywhere.
Secondly, I think you are mixing views and view controllers.
Finally, your view controller that handles FB authorization (loginView) should implement
FBRequestDelegate,FBDialogDelegate,FBSessionDelegate
So your loginView.h should look something like:
#interface loginView : UIViewController <
FBRequestDelegate,FBDialogDelegate,FBSessionDelegate>{