Cannot get delegate to work between my views - ios

I need to call some methods from one view to another, and I can't seem to get it to work. What am I doing wrong?
Here's my ViewController.h
#import <UIKit/UIKit.h>
#import "mySettings.h"
#protocol ViewControllerDelegate <NSObject>
#required
- (void) getDefaults;
- (void) updateSubTotal: ( float ) value;
#end
#interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> {
id <ViewControllerDelegate> delegate;
}
#property (retain) id delegate;
.
. (other declarations)
.
#end
ViewController.m
#import "ViewController.h"
#import "mySettings.h"
#interface ViewController ( )
#property (assign) mySettings *settingsVC;
#end
#implementation ViewController
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
// Do any additional setup after loading the view, typically from a nib.
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.Just-The-Tip"] ;
[ self getDefaults ] ;
self.arrPercent = # [ #"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20",#"21",#"22",#"23",#"24",#"25",#"26",#"27",#"28",#"29",#"30",#"31",#"32",#"33",#"34",#"35",#"36",#"37",#"38",#"39",#"40",#"41",#"42",#"43",#"44",#"45",#"46",#"47",#"48",#"49",#"50" ] ;
self.arrPeople = # [ #"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20" ] ;
self.myPicker.dataSource = self;
self.myPicker.delegate = self;
if ( self.bRememberLastBill )
{
self.subtotal = [ self.userDefaults floatForKey:#"sub_total" ] ;
self.strSubTotal = [ NSString stringWithFormat: #"%.2f", self.subtotal ] ;
[ self updateSubTotal:-3 ] ;
}
// BEGIN ENABLE DONE BUTTON FOR NUMPAD
UIToolbar * keyboardDoneButtonView = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 32)];;
keyboardDoneButtonView.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc] initWithTitle:#"Clear" style:UIBarButtonItemStyleDone target:self action:#selector(clearClicked:)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneClicked:)], nil
];
[keyboardDoneButtonView sizeToFit];
self.field_SubTotal.inputAccessoryView = keyboardDoneButtonView;
// END ENABLE DONE BUTTON FOR NUMPAD
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 16, 60)];
self.field_SubTotal.rightView = paddingView;
self.field_SubTotal.rightViewMode = UITextFieldViewModeAlways;
self.settingsVC = [[mySettings alloc] init];
self.settingsVC.delegate = self ;
[ self animate ] ;
}
- ( void ) getDefaults
{
// lots of stuff here
}
- ( void ) updateSubTotal: ( float ) value
{
// even more code here
}
mySettings.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface mySettings : UIViewController {
}
#property (nonatomic, assign) id delegate;
.
. (a bunch of declarations)
.
#end
mySettings.m
#import "mySettings.h"
#import "ViewController.h"
#interface mySettings ( )
#end
#implementation mySettings
#synthesize delegate;
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
// Do any additional setup after loading the view.
//self.userDefaults = [ NSUserDefaults standardUserDefaults ] ;
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.Just-The-Tip"] ;
[ self getDefaults ] ;
self.textDefaultTax.text = [ NSString stringWithFormat:#"%.3f", self.default_tax ] ;
self.textDefaultTip.text = [ NSString stringWithFormat:#"%.f", self.default_tip ] ;
// BEGIN ENABLE DONE BUTTON FOR NUMPAD
UIToolbar * keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneClicked:)],
nil]];
[keyboardDoneButtonView sizeToFit];
self.textDefaultTip.inputAccessoryView = keyboardDoneButtonView;
self.textDefaultTax.inputAccessoryView = keyboardDoneButtonView;
// END ENABLE DONE BUTTON FOR NUMPAD
[ self animate ] ;
}
// a few methods later
- (IBAction)up_default_exclude_tax:(id)sender {
self.bExcludeTax = self.switchExcludeTax.isOn;
[ self setDefaults ] ;
[ self.delegate getDefaults ];
[ self.delegate updateSubTotal:-3 ];
}

Frankly, you have almost confused me :). The way you are implementing delegate design pattern and connecting view controllers is not the suggested/documented way of doing it.
Lets proceed step by step.
Step 1: MySettings (like UITableViewController) implements some feature and relies on its delegate to implement others.
So, following points to take away from here:
protocol definition must be MySettingsDelegate and not ViewControllerDelegate.
rename mySettings to MySettingsViewController.
MySettingsViewController should not import ViewController. It must use its delegate property to interact with ViewController.
This is how my MySettingsViewController would look like post these changes.
MySettingsViewController.h
`
#protocol MySettingsViewControllerDelegate <NSObject>
#required
- (void) getDefaults;
- (void) updateSubTotal: ( float ) value;
#end
#interface MySettingsViewController : UIViewController {
}
#property (nonatomic, assign) id delegate;
.
. (a bunch of declarations)
.
#end`
Step2: You don't need to call #synthesis on properties any more. Also, before calling a method on delegate it is always good practice to do a nil check. Please see how my MySettingsViewController.m would look like. I have also added some NSLog statement for you to verify if controls comes there or not.
MySettingsViewController.m
#implementation MySettingsViewController
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
// Do any additional setup after loading the view.
//self.userDefaults = [ NSUserDefaults standardUserDefaults ] ;
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.Just-The-Tip"] ;
[ self getDefaults ] ;
self.textDefaultTax.text = [ NSString stringWithFormat:#"%.3f", self.default_tax ] ;
self.textDefaultTip.text = [ NSString stringWithFormat:#"%.f", self.default_tip ] ;
// BEGIN ENABLE DONE BUTTON FOR NUMPAD
UIToolbar * keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneClicked:)],
nil]];
[keyboardDoneButtonView sizeToFit];
self.textDefaultTip.inputAccessoryView = keyboardDoneButtonView;
self.textDefaultTax.inputAccessoryView = keyboardDoneButtonView;
// END ENABLE DONE BUTTON FOR NUMPAD
[ self animate ] ;
}
// a few methods later
- (IBAction)up_default_exclude_tax:(id)sender {
self.bExcludeTax = self.switchExcludeTax.isOn;
[self setDefaults];
NSLog(#"Action taken");
if (self.delegate && [self.delegate respondsToSelector:#selector(getDefaults)]) {
NSLog(#"Calling getDefaults");
[self.delegate getDefaults];
}
if (self.delegate && [self.delegate respondsToSelector:#selector(updateSubTotal:)]) {
NSLog(#"Calling updateSubTotal:");
[self.delegate updateSubTotal:-3];
}
}
Step 3: Now, that my support class ready, lets use it. Time to write ViewController class. Not sure why you added delegate in header of ViewController as well, we literally do not need it here. This is how my ViewController.h will look like:
ViewController.h
#interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate, MySettingsViewControllerDelegate> {
}
.
. (other declarations)
.
#end
Steps 4: Now comes the main part. Please ensure you hold a strong reference to MySettingsViewController. This is how my ViewController.m would look like:
ViewController.m
#interface ViewController()
#property (nonatomic, strong) MySettingsViewController *settingsVC;
#end
- ( void ) viewDidLoad {
[super viewDidLoad ] ;
// Do any additional setup after loading the view, typically from a nib.
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.Just-The-Tip"] ;
[ self getDefaults ] ;
self.arrPercent = # [ #"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20",#"21",#"22",#"23",#"24",#"25",#"26",#"27",#"28",#"29",#"30",#"31",#"32",#"33",#"34",#"35",#"36",#"37",#"38",#"39",#"40",#"41",#"42",#"43",#"44",#"45",#"46",#"47",#"48",#"49",#"50" ] ;
self.arrPeople = # [ #"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20" ] ;
self.myPicker.dataSource = self;
self.myPicker.delegate = self;
if ( self.bRememberLastBill )
{
self.subtotal = [ self.userDefaults floatForKey:#"sub_total" ] ;
self.strSubTotal = [ NSString stringWithFormat: #"%.2f", self.subtotal ] ;
[ self updateSubTotal:-3 ] ;
}
// BEGIN ENABLE DONE BUTTON FOR NUMPAD
UIToolbar * keyboardDoneButtonView = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 32)];;
keyboardDoneButtonView.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc] initWithTitle:#"Clear" style:UIBarButtonItemStyleDone target:self action:#selector(clearClicked:)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneClicked:)], nil
];
[keyboardDoneButtonView sizeToFit];
self.field_SubTotal.inputAccessoryView = keyboardDoneButtonView;
// END ENABLE DONE BUTTON FOR NUMPAD
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 16, 60)];
self.field_SubTotal.rightView = paddingView;
self.field_SubTotal.rightViewMode = UITextFieldViewModeAlways;
self.settingsVC = [[MySettingsViewController alloc] init];
self.settingsVC.delegate = self ;
[ self animate ] ;
}
- ( void ) getDefaults
{
// lots of stuff here
}
- ( void ) updateSubTotal: ( float ) value
{
// even more code here
}
I believe this must solve your issue and would bring clarity to delegate pattern. You also need to ensure that while MySettingsViewController is active and calls its delegate, ViewController also stays in memory.
Edit: If you are using storyboard
Please ensure you are setting the delegate correctly on the right object. Do not instantiate your own object.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"SegueRegistrationUserAction"]) {
[(MySettingsViewController *)segue.destinationViewController setDelegate:self];
}
}
Final Edit (Fixed in Code):
So, I took a look at your code and found the issue. It was apparently different objects issue. You are using storyboard and also creating a mySettings object in code as well. When you connect via storyboard, you should use the object created from storyboard and avoid creating your own. When I changed the below method in your ViewController.m, it fixed the issue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
self.settingsVC = (mySettings *)segue.destinationViewController;
self.settingsVC.delegate = self;
}

Assuming you want to send data from your ViewController to your Settings via the delegate pattern.In your Settings.h:
#import <UIKit/UIKit.h>
#protocol SettingsDelegate
#required
- (void) getDefaults;
- (void) updateSubTotal: ( float ) value;
#end
#interface Settings : UIViewController
#property (weak, nonatomic) id<ViewControllerDelegate> delegate;
#end
Then in your ViewController.h
#import "Settings.h"
#interface Settings : UIViewController<ViewControllerDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
#end
This basically says that your ViewController is going to contain the delegate methods that you defined in the SettingsDelegate protocol.
So in your ViewController.m:
#interface ViewController ()
#end
#implementation ViewController
- (void) viewDidLoad{
viewController.delegate = self; //somehow get a copy of your viewController instance and set the delegate. This doesn't have to be in viewDidLoad, but it needs to happen sometime.
}
- (void) getDefaults{
//Do stuff. You probably want to change the return type to something other than void if we are actually getting defaults here.
}
- (void) updateSubTotal: ( float ) value{
//Do stuff.
}
...
#end
Then in your Settings.m, when the appropriate time comes. you can call:
[self.delegate getDefaults];

Related

plugins in keywindow can't response user events?

In my viewcontroller like this:
#import "PPSharedView.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
PPSharedView * sharedView = [[PPSharedView alloc] init];
sharedView.topImageName = #"fenxiangdao";
[sharedView sharedWithArrayImage:#[#"weixin_um",#"weixin_um",#"weixin_um",] titles:#[#"微信好友",#"微信好友",#"微信好友",]];
}
#end
In PPSharedView.h like this:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface PPSharedView : UIView
-(void)sharedWithArrayImage:(nonnull NSArray *)arrImgs
titles:(nonnull NSArray *)arrTitles;
#end
In PPSharedView.m on the below:
-(void)sharedWithArrayImage:(NSArray *)arrImgs titles:(NSArray *)arrTitles{
if (arrImgs.count != arrTitles.count) return;
UIWindow * keyWindow = [UIApplication sharedApplication].keyWindow;
UIView * backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kSCREEN_W, kSCREEN_H)];
[keyWindow addSubview:backView];
backView.backgroundColor = [UIColor blackColor];
backView.alpha = 0.5;
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(clickRedview)];
backView.userInteractionEnabled = YES;
[backView addGestureRecognizer:tap];
}
-(void)clickRedview{
NSLog(#"adf");
}
When I run the app on the iPhone the backView on the screen but can't response click events.Anyone knows what's wrong with the code?Thank you very much!
In controller the sharedView should be referenced example:
#interface ViewController ()
#property(nonatomic, strong) PPSharedView * ppView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
PPSharedView * sharedView = [[PPSharedView alloc] init];
self.ppView = sharedView;
sharedView.topImageName = #"fenxiangdao";
[sharedView sharedWithArrayImage:#[#"weixin_um",#"weixin_um",#"weixin_um",] titles:#[#"微信好友",#"微信好友",#"微信好友",]];
}
#end
If don't do this the sharedView will be destoryed!

Why does NavgationItem reference disappears?

I created a NavigationBar and added it to the UIViewController. But after init, the reference turns to nil. I'm new to iOS and OC, I don't know why. Anyone can help? Thank you.
code summary:
#interface ContainerViewController()
#property (nonatomic, retain) UINavigationBar *nav;
#property (nonatomic, retain) UINavigationItem *navItem;
#end
#implementation ContainerViewController
- (instancetype) initWithParams:(NSDictionary *)params {
self = [super init];
if (self) {//...}
return self;
}
- setNavTitle:(NSDictionary *) params {
NSString *title = params[#"title"];
/////////////////////////////////
// here goes wrong
// self.navItem == nil here, why?
/////////////////////////////////
self.navItem.title = title;
}
- (void) viewWillAppear:(Bool)animated {
[super viewWillAppear:NO];
static float navHeight = 64.0;
UIViewController *wvController = [WebView init here];
UINavigationBar *nav = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), navHeight)];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:title];
nav.items = [NSArray arrayWithObjects: navItem, nil];
///////////////////////////////
// I saved the reference here
//////////////////////////////
[self setNav:nav];
[self setNavItem:navItem];
[self.view addSubview:nav];
[self addChildViewController:wvController];
wvController.view.bounds = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - navHeight);
[self.view addSubview:wvController.view];
[wvController didMoveToParentViewController:self];
}
#end
This will be useful for you, kindly check and do
Tutorial point site is very easy to learn some important UI basics if you are working in Objective C

I have an issue with an UIAlertView showing repeatedly can't find the source

My problem is this, in the app when a user clicks somewhere not important an alertView is raised that's ok, I can find the call to that view, but then is showing again and again empty and I have placed breakpoint everywhere I see a call to any alert. But the ghost alert is not breaking anywhere I have no idea who is throwing it is just a sentient view.
Can you give some tips on how to pin point where is the view being called?
EDIT:
Code for the viewController:
#import <CoreLocation/CoreLocation.h>
#import "FormViewController.h"
#import "FormPageViewController.h"
#import "FormElement+UtilityMethods.h"
#import "UserBO.h"
#import "RecordBO.h"
#import "RecordAnswer.h"
#import "UserDefaultsUtilities.h"
#import "TimeTrackingUtilities.h"
#import "DxColors.h"
#import "EDQueueUtilities.h"
#import "GroupAnswerMetadata.h"
#import "RecordAnswer+UtilityMethods.h"
#import "Record+UtilityMethods.h"
#import "FormPageIndexViewController.h"
#import "ManagedObjectUtilities.h"
#import "EDQueue.h"
#import "EDQueueUtilities.h"
#import "DxAnswerObject.h"
#import "ImageAnswerMetadata.h"
#import "DateUtilities.h"
#import <ifaddrs.h>
#import "CarbonKit.h"
#define INITIAL_CONTROLLER_INDEX 0
#define FORM_RECORDS_TEMP_NAME #"<~TMP>"
#define TAG_RETURN_BUTTON 0
#define TAG_SAVE_BUTTON 1
#define TAG_SEND_BUTTON 2
typedef NS_ENUM(NSUInteger, AlertViewPurpose) {
ALERT_VIEW_FORM_NONE = 0,
ALERT_VIEW_FORM_SEND_SUCCESS = 1,
ALERT_VIEW_FORM_SEND_FAILURE = 2,
ALERT_VIEW_FORM_SAVE_PROMPT = 3,
ALERT_VIEW_FORM_FILE_NAME_PROMPT = 4,
ALERT_VIEW_FORM_ASYNC_SEND_SUCCESS = 5,
ALERT_VIEW_FORM_COULDNT_SEND = 6,
ALERT_VIEW_FORM_WANT_TO_SEND = 7,
ALERT_VIEW_FORM_SAVE_IN_CONTEXT_PROMPT = 8,
ALERT_VIEW_FORM_FILE_NAME_IN_CTXT_SAVE_PROMPT = 9,
ALERT_VIEW_FORM_REQUIRED_INTERNET_CONECTION = 10,
// Enumeration counter.
ALERT_VIEW_PURPOSE_COUNT
};
// Based on:
// Ref.: http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
#interface FormViewController () <RecordBOProtocol, FieldElementProtocol,
CLLocationManagerDelegate, FormPageIndexProtocol,CarbonTabSwipeNavigationDelegate>
{
AlertViewPurpose _currentAlertViewPurpose;
CarbonTabSwipeNavigation *_carbonTabSwipeNavigation;
BOOL _unedited;
BOOL _formRecordNilAtStartUp;
BOOL _timestampTaken;
CLLocationManager *_locationManager;
CLLocation *_location;
NSDate *_timeSpentBaseTimestamp;
NSArray *_sortedPages;
NSUInteger _currentPageIndex;
NSString *formID;
NSArray *_pagesNames;
}
#property (weak, nonatomic) IBOutlet UILabel *lblFormTitle;
#property (weak, nonatomic) IBOutlet UIButton *btnSmallReturn;
#property (weak, nonatomic) IBOutlet UIButton *btnSmallSave;
#property (weak, nonatomic) IBOutlet UIButton *btnSmallSend;
#property (weak, nonatomic) IBOutlet UIButton *btnBigSend;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *btnReturn;
#property (strong, nonatomic) IBOutlet UIButton *lblBack;
#property (strong, nonatomic) IBOutlet UIButton *lblSave;
#end
#implementation FormViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
_currentAlertViewPurpose = ALERT_VIEW_FORM_NONE;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self localizedButtons];
// Starting up location manager if form requires it.
// Ref.:
// https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestAlwaysAuthorization
if ([self.form.geolocationEnabled boolValue]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
if ([CLLocationManager locationServicesEnabled]) {
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined) {
// Requesting authorization.
if ([CLLocationManager instancesRespondToSelector:#selector(requestWhenInUseAuthorization)]) {
#ifdef DEBUG_MODE
NSAssert(
[[[NSBundle mainBundle] infoDictionary] valueForKey:#"NSLocationWhenInUseUsageDescription"],
#"For iOS 8 and above, your app must have a value for NSLocationWhenInUseUsageDescription in its Info.plist");
#endif // DEBUG_MODE
[_locationManager requestWhenInUseAuthorization];
}
} else if (status == kCLAuthorizationStatusAuthorizedAlways ||
status == kCLAuthorizationStatusAuthorizedWhenInUse) {
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[_locationManager startUpdatingLocation];
}
}
}
self.lblFormTitle.text = self.form.name ;
// Saving whether self.formRecord was nil at beginning.
// Important for time spent tap calculations.
_formRecordNilAtStartUp = self.formRecord == nil;
[self setup];
//Take the time for counting
_timeSpentBaseTimestamp = [NSDate date];
_unedited = YES;
}
-(void)localizedButtons
{
[self.lblBack setTitle:NSLocalizedString(#"Back", #"Regresar") forState:UIControlStateNormal];
[self.lblSave setTitle:NSLocalizedString(#"Save", #"Guardar") forState:UIControlStateNormal];
[self.btnBigSend setTitle:NSLocalizedString(#"Send", #"Enviar") forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Overriding from DxBaseViewController.
-(void)refresh
{
}
-(void)setup
{
// Obtaining sorted pages array.
_sortedPages = [[self.form.pages allObjects]
sortedArrayUsingComparator:^NSComparisonResult(Page *obj1, Page * obj2) {
return [obj1.pageNumber compare: obj2.pageNumber];
}];
//Adding toolBar
NSMutableArray *namesPages = [[NSMutableArray alloc]init];
for (Page *page in _sortedPages) {
NSString *namePage = page.name;
[namesPages addObject:namePage];
}
_pagesNames = [namesPages copy] ;
// Creating by default a record in case there's none.
if (self.formRecord == nil) {
self.formRecord = [Record createInContext:self.managedObjectContext];
// Filling in basic record information.
self.formRecord.name = FORM_RECORDS_TEMP_NAME;
self.formRecord.editable = self.form.editableRecords;
self.formRecord.dateLastSaved = self.formRecord.dateCreated = [NSDate date];
self.formRecord.syncStatusId = [NSNumber numberWithInt:SYNC_STATUS_NOT_SYNCED];
self.formRecord.user = [UserBO loggedInUser];
self.formRecord.form = self.form;
self.formRecord.formId = self.form.pkey;
self.formRecord.temporary = [NSNumber numberWithBool:YES];
self.formRecord.isBeingEdited = [NSNumber numberWithBool:YES];
// Committing record information as is. It will be removed if user doesn't
// want to save changes.
if (![Record commitChangesFromContext:self.managedObjectContext]) {
DebugLog(#"Temp form record couldn't be saved! Check!");
}
// Initializing page view controller.
_carbonTabSwipeNavigation =[[CarbonTabSwipeNavigation alloc] initWithItems:_pagesNames
delegate:self];
_carbonTabSwipeNavigation.toolbar.barTintColor = [DxColors colorWithHexRGB:NEW_FORMS_GREEN];
[_carbonTabSwipeNavigation setNormalColor:[UIColor whiteColor]];
[_carbonTabSwipeNavigation setIndicatorColor:[UIColor whiteColor]];
[_carbonTabSwipeNavigation setSelectedColor:[UIColor whiteColor]];
} else {
[self prepareControllerForEdition];
}
[_carbonTabSwipeNavigation insertIntoRootViewController:self];
self.pageViewController = _carbonTabSwipeNavigation.pageViewController;
}
- (UIViewController *)carbonTabSwipeNavigation:(CarbonTabSwipeNavigation *)carbontTabSwipeNavigation
viewControllerAtIndex:(NSUInteger)index {
_currentPageIndex = index;
// Create a new view controller and pass suitable data.
FormPageViewController *formPageViewController = [[FormPageViewController alloc] init];
formPageViewController.pageIndex = index;
formPageViewController.formPage = _sortedPages[index];
formPageViewController.managedObjectContext = self.managedObjectContext;
formPageViewController.formRecord = self.formRecord;
formPageViewController.observer = self;
formPageViewController.view.frame = CGRectMake(0,
0,
self.view.frame.size.width,
self.view.frame.size.height);
return formPageViewController;
}
#pragma mark - Button Actions (IBActions)
-(IBAction)send:(id)sender
{
_timer = [NSTimer scheduledTimerWithTimeInterval:0.001
target:self
selector:#selector(isAlertViewShowing:)
userInfo:nil
repeats:YES];
[self setButtonWithTag:self.btnBigSend.tag toHighlight:NO];
// Disabling button to avoid double submissions.
self.btnBigSend.enabled = NO;
// Show alert.
[self showAreYouReadyToSubmitFormMsg];
}
... can't paste it all
For testing only:
Subclass UIAlertView i.e. #interface MyAlertView : UIAlertView
Then replace all instances of UIAlertView from MyAlertView
i.e. MyAlertView *someAlert = [[MyAlertView alloc] init.......];
Then override
-(void)show {
[super show];
//Your breakpoint here
OR
NSLog([NSThread callStackSymbols]);
}
Check your viewcontroller that has an uialertviewdelegate.
Log your alertview.delegate
Check your super class of a viewcontroller that it doesn't call uialertviewdelegate function.
If it is an UIAlertController, check viewwillappear, viewdidappear, viewwilldisappear (super class too) and find out they don't call [alertview show]
Why you take enum for alertview ? just make instance of UIAlertView where it require's to show. you can make one method in which you can pass two string parameters alertview massage and title and method shows alertview with this title and massage.
You can catch the content of your AlertView, if it has no content at all, don't present it!
To do this check the message you are passing to the method that presents the alertView.
However, I can't seem to find your method showAreYouReadyToSubmitFormMsg.

Why isn't my method call working from a different class?

I am a new programmer, and know the basics of IOS and Objective C Programming, but have run into a bug.
All I am trying to do is when a button is clicked, it calls a method from another class.
The Method I am trying to call is: [phoneCompany printPrompt];
So here is my code:
First Class: (ViewController)
.m
#import "ViewController.h"
#import "PhoneCompany.h"
#implementation ViewController
#synthesize dialTextField;
#synthesize dialButton;
#synthesize textFromCall;
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.dialTextField = [[UITextField alloc]initWithFrame:CGRectMake(83, 101, 154, 30)];
self.dialTextField.borderStyle = UITextBorderStyleRoundedRect;
self.dialTextField.placeholder = #"Dial Number";
self.dialTextField.textAlignment = NSTextAlignmentCenter;
self.dialTextField.adjustsFontSizeToFitWidth = YES;
self.dialTextField.minimumFontSize = 20;
self.dialTextField.autocorrectionType = NO;
self.dialTextField.returnKeyType = UIReturnKeyDone;
self.dialTextField.backgroundColor = [UIColor lightGrayColor];
self.dialTextField.delegate = self;
[self.view addSubview:self.dialTextField];
self.dialButton= [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.dialButton setTitle:#"Dial!" forState:UIControlStateNormal];
self.dialButton.titleLabel.font = [UIFont systemFontOfSize:20];
[self.dialButton setBackgroundColor:[UIColor blueColor]];
[self.dialButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.dialButton addTarget:self action:#selector(mainCall) forControlEvents:UIControlEventTouchUpInside];
self.dialButton.frame =CGRectMake(92, 400, 125, 30);
[self.view addSubview:self.dialButton];
self.textFromCall = [[UILabel alloc]initWithFrame:CGRectMake(48,155,220,240)];
[self.textFromCall setText:#"Hello, what number would you like to call?"];
self.textFromCall.numberOfLines = 0;
self.textFromCall.lineBreakMode = UILineBreakModeWordWrap;
self.textFromCall.adjustsFontSizeToFitWidth = YES;
[self.textFromCall setTextAlignment:NSTextAlignmentCenter];
[self.textFromCall setTextColor:[UIColor blackColor]];
[self.textFromCall setBackgroundColor:[UIColor clearColor]];
[self.view addSubview: self.textFromCall];
}
-(void) mainCall{
if([self.dialTextField.text isEqualToString:#"1234567"]){
self.dialButton.enabled = NO;
self.dialTextField.enabled = NO;
PhoneCompany *phoneCompany = [[PhoneCompany alloc]init];
[NSTimer scheduledTimerWithTimeInterval: 3 target:phoneCompany selector:#selector(printPrompt)
userInfo:nil repeats:NO];
self.textFromCall.text = #"Dialing...";
[NSTimer scheduledTimerWithTimeInterval: 1 target:self selector:#selector(connectingStatement)
userInfo:nil repeats:NO];
}
else if([self.dialTextField.text isEqualToString: nil]){
self.textFromCall.text = #"Please enter a phone number.";
}
else{
self.textFromCall.text = #"Invalid Phone number.";
}
}
-(void)connectingStatement{
self.textFromCall.text = #"Connecting...";
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic) UITextField *dialTextField;
#property (weak,nonatomic) UIButton *dialButton;
#property (strong,nonatomic) UILabel *textFromCall;
-(void) mainCall;
-(void) connectingStatement;
-(void) setString:(NSString *)string;
#end
Now here is the Second Class: (PhoneCompany)
.h
#import <Foundation/Foundation.h>
#interface PhoneCompany : NSObject
-(void) printPrompt;
#end
.m
#import "PhoneCompany.h"
#import "ViewController.h"
#implementation PhoneCompany
-(void) printPrompt{
ViewController *mainView = [[ViewController alloc]init];
mainView.dialTextField.text = #"Test";
}
#end
Your call to printPrompt is fine. The problem is that you are creating a new ViewContoller in the function. The one you created in printPrompt is not the same one where you call that function. I means setString: won't replace the text of textFromCall textfield. Somehow you need to pass ViewController to PhoneCompany as a delegate and call the setString: from it.
Edited:
Try this -
In PhoneCompany.h
#class PhoneCompany;
#protocol PhoneCompanyDelegate <NSObject>
-(void)phoneCompany:(PhoneCompany *)phoneCompay
setString:(NSString *)string;
#end
#interface PhoneCompany : NSObject
#property (nonatomic, assign)id<PhoneCompanyDelegate>delegate;
- (id)initWithDelegate:(id<PhoneCompanyDelegate>)delegate;
- (void) printPrompt;
#end
In PhoneCompay.m
#implementation PhoneCompany
- (id)initWithDelegate:(id<PhoneCompanyDelegate>)delegate
{
self = [super init];
if (self)
{
self.delegate = delegate;
}
return self;
}
-(void) printPrompt
{
if (self.delegate && [self.delegate respondsToSelector:#selector(phoneCompany:setString:)])
{
[self.delegate phoneCompany:self
setString:#"Test"];
}
}
#end
When you create the PhonCompany Object in prinPrompt
PhoneCompany *phoneCompay = [[PhoneCompany alloc] initWithDelegate:self];
In your ViewController.h
#import "PhoneCompany"
#interface ViewController:UIViewController<PhoneCompanyDelegate>
It turns out, all I had to do was declare the textFromCall as a static UILabel *textFromCall, and then declare a method to edit the text. Thanks for all your answers!

MGSplitViewController not as RootView but within a UIViewController

I'm very new to iOS programming (Coming from Java / C++). I'm trying to set up an app with a TabBarController of which one tab should be a SplitView. I've done my research and I know that UISplitview will not work and everywhere people recommend using the MGSplitViewController. I've looked at the demo but I just can't figure out how to use it without it beeing the app's root view and can't find any sample code that could help
So here is what I do with the classes from the demo in a separate UIViewController class that I afterwards add to the TabBarController: This is my class:
#import <UIKit/UIKit.h>
#import "MGSplitCornersView.h"
#import "RootViewController.h"
#import "DetailViewController.h"
#interface ChannelViewController : UIViewController {
MGSplitViewController *splitViewController;
RootViewController *rootViewController;
DetailViewController *detailViewController;
}
#property (nonatomic, retain) MGSplitViewController *splitViewController;
#property (nonatomic, retain) RootViewController *rootViewController;
#property (nonatomic, retain) DetailViewController *detailViewController;
#end
And this is my desperate try to set it up
- (id)initWithTabBar
{
self = [super init];
//this is the label on the tab button itself
self.title = #"SplitView";
//use whatever image you want and add it to your project
//self.tabBarItem.image = [UIImage imageNamed:#"name_gray.png"];
// set the long name shown in the navigation bar at the top
self.navigationItem.title=#"Nav Title";
self.splitViewController = [[MGSplitViewController alloc] init];
self.rootViewController = [[RootViewController alloc] init];
self.detailViewController = [[DetailViewController alloc] init];
[self.splitViewController setDetailViewController:detailViewController];
[self.splitViewController setMasterViewController:rootViewController];
[self.view addSubview:splitViewController.view];
[self.rootViewController performSelector:#selector(selectFirstRow) withObject:nil afterDelay:0];
[self.detailViewController performSelector:#selector(configureView) withObject:nil afterDelay:0];
if (NO) { // whether to allow dragging the divider to move the split.
splitViewController.splitWidth = 15.0; // make it wide enough to actually drag!
splitViewController.allowsDraggingDivider = YES;
}
return self;
}
I guess I'm doing something wrong with delegates? Or do I have something else mixed up?
Is the demo doing things in the IB that I can't see in the code?
I get the split view but no content and especially no navigation bar with the buttons the demo comes with.
I'd be very thankful for hints or sample code!
Ok manny, here we go. This is my working code for the interface:
#import <UIKit/UIKit.h>
#import "MGSplitViewController.h"
#import "ecbView.h"
#import "ecbCalc.h"
#interface splitMain : MGSplitViewController <UIPopoverControllerDelegate,
MGSplitViewControllerDelegate>
{
IBOutlet UIPopoverController* popoverController;
IBOutlet UINavigationController* naviController;
IBOutlet ecbCalc* viewCalcLeft;
IBOutlet ecbView* euroRatesRight;
UIBarButtonItem* savedButtonItem;
BOOL keepMasterInPortraitMode;
BOOL memoryWasDropped;
BOOL viewLoaded;
}
#property (nonatomic, retain) UIPopoverController* popoverController;
#property (nonatomic, retain) UINavigationController* naviController;
#property (nonatomic, retain) ecbCalc* viewCalcLeft;
#property (nonatomic, retain) ecbView* euroRatesRight;
#property (nonatomic, retain) UIBarButtonItem* savedButtonItem;
#property (nonatomic, readonly) BOOL keepMasterInPortraitMode;
#property (nonatomic, readonly) BOOL memoryWasDropped;
#property (nonatomic, readonly) BOOL viewLoaded;
- (void)dismissPopoverController: (BOOL)animated;
- (void)settingsChanged;
#end
and here excerpts from implementation file:
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
// my initialization...
}
return self;
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
CGRect rectFrame = CGRectMake(0.0, 20.0, 768.0, 1004.0 - 48.0); // being above a tab bar!
viewLoaded = NO;
self.view = [[UIView alloc] initWithFrame:rectFrame];
viewCalcLeft = [[ecbCalc alloc] initWithNibName:#"ecbCalc" bundle:nil];
euroRatesRight = [[ecbView alloc] initWithNibName:#"ecbView-iPad" bundle:nil];
naviController = [[UINavigationController alloc] initWithRootViewController:self.viewCalcLeft];
naviController.navigationBar.barStyle = UIBarStyleBlack;
naviController.title = nil;
viewCalcLeft.title = NSLocalizedString(#"BtnTitleCalc", #"");
viewCalcLeft.view.hidden = NO;
NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults];
if ([prefs objectForKey:#"iPadAlwaysSplitTableView"] != nil)
self.keepMasterInPortraitMode = [prefs boolForKey:#"iPadAlwaysSplitTableView"];
else
self.keepMasterInPortraitMode = YES;
NSArray* theViewControllers = [NSArray arrayWithObjects:self.naviController, self.euroRatesRight, nil];
[self setViewControllers:theViewControllers];
[self setDelegate:self];
[self setShowsMasterInPortrait:keepMasterInPortraitMode];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
// protection because this one is called twice
if (viewLoaded)
return;
[super viewDidLoad];
if (memoryWasDropped)
{
if (!self.keepMasterInPortraitMode && UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
// recreate popover controller
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:self.viewCalcLeft];
}
}
viewLoaded = YES;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
memoryWasDropped = YES;
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self dismissPopoverController:NO];
self.popoverController = nil;
self.naviController = nil;
self.viewCalcLeft = nil;
self.euroRatesRight = nil;
viewLoaded = NO;
}
My MainWindow.xib has a UITabBarController and the button for splitMain is configured for this class but with an empty xib entry. So creation has to go via loadView. Maybe I could have done the viewDidLoad stuff within loadView ... but so I had to protect viewDidLoad from being called twice. That happens in loadView as soon as the view is instantiated from MGSplitViewController class because the initWithCoder there is calling [self setup]. In that function the frame rect is calculated with self.view.bounds so that viewDidLoad is called again because the view doesn't exist yet. Maybe one could implement a workaround within MGSplitViewController.m but I was too lazy doing that.
To get this working on a tab bar controller please make sure you commit most of the changes that are published on the MGSplitViewController's git page. Good luck.

Resources