I have a table view controller with custom derived cells. When somebody clicks a button in the cell (the editButton below), I want to load a different view controller to display a pop up dialog.
I created a xib and view controller, and loaded the new VC that way, but everything in the new VC object was nil, and the new VC didn't appear.
I then tried programaticaly creating the view, using the initWithDefaultText:origin: initializer, but it still doesn't appear, but the member widgets are now valid.
Am I missing something?
MyListTableViewCell.h
#interface MyListTableViewCell : UITableViewCell <MyEditQueryDelegate>
...
MyListTableViewCell.m
#implementation MyListTableViewCell
+ (MyListTableViewCell *)loadFromNibWithItem:(MyListItem *)item
expandHandler:(MyItemExpandHandler)handler
controller:(MyListViewController*)controller
{
MyListTableViewCell *cell = [[[NSBundle mainBundle]
loadNibNamed:#"MyListTableViewCell" owner:self options:nil] objectAtIndex:0];
cell.item = item;
cell.expandHandler = handler;
cell.queryLabel.text = item.displayText;
[cell hideOptions];
[cell.editButton addTarget: cell action: #selector(editButtonTapped:)
forControlEvents: UIControlEventTouchUpInside];
return cell;
}
- (void) editButtonTapped: (UIButton*) sender
{
CGPoint globalOrigin = [self.superview convertPoint:self.frame.origin toView:nil];
NSLog(#"editButtonTapped Point (%f, %f).", globalOrigin.x, globalOrigin.y);
// This log message appears.
// MyEditQueryViewController* vc = [[MyEditQueryViewController alloc]
// initWithNibName:#"MyEditQueryView" bundle:nil];
// This resulted in a nil view in the vc and no visual change.
MyEditQueryViewController* vc = [[MyEditQueryViewController alloc]
initWithDefaultText:[self.queryLabel text] orign:globalOrigin];
vc.delegate = self;
[_controller presentViewController: vc animated: YES completion: nil];
// vc should appear here????
}
MyEditQueryViewController.h
#import <UIKit/UIKit.h>
#import "MyEditQueryDelegate.h"
#interface MyEditQueryViewController : UIViewController
#property (nonatomic, strong) id<MyEditQueryDelegate> delegate;
#property (nonatomic, strong) IBOutlet UITextField* textField;
#property (nonatomic, strong) IBOutlet UIView* editView;
#property (nonatomic, strong) IBOutlet UIButton* cancelButton;
#property (nonatomic, strong) IBOutlet UIButton* saveButton;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
- (id)initWithDefaultText:(NSString*)defaultText orign:(CGPoint)origin;
- (IBAction)cancelTapped:(id)sender;
- (IBAction)saveTapped:(id)sender;
#end
MyEditQueryViewController.m
#implementation MyEditQueryViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(#"initWithNibName:bundle:");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
}
return self;
}
- (id)initWithDefaultText:(NSString*)defaultText orign:(CGPoint)origin
{
NSLog(#"initWithDefaultText:origin:");
self = [super initWithNibName: nil bundle:nil];
if (self)
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
self.view = [[UIView alloc] initWithFrame:screenRect];
UIImage* smokeGlass = [UIImage imageNamed:#"SmokeGlass.png"];
UIImageView* background = [[UIImageView alloc] initWithImage:smokeGlass];
[self.view addSubview:background];
CGRect editViewFrame = CGRectMake(0.0, origin.y, screenRect.size.width, 122.0);
_editView = [[UIView alloc] initWithFrame:editViewFrame];
[self.view addSubview: _editView];
CGRect textViewFrame = CGRectMake(20.0, 20.0, 280.0, 30.0);
_textField = [[UITextField alloc] initWithFrame: textViewFrame];
_textField.text = defaultText;
[_editView addSubview: _textField];
CGRect cancelButtonFrame = CGRectMake(20.0, 72.0, 50.0, 30.0);
_cancelButton = [[UIButton alloc] initWithFrame:cancelButtonFrame];
_cancelButton.titleLabel.text = #"Cancel";
[_cancelButton addTarget:self action:#selector(cancelTapped:)
forControlEvents:UIControlEventTouchUpInside];
[_editView addSubview: _cancelButton];
CGRect saveButtonFrame = CGRectMake(266.0, 72.0, 34.0, 30.0);
_saveButton = [[UIButton alloc] initWithFrame:saveButtonFrame];
_saveButton.titleLabel.text = #"Save";
[_saveButton addTarget:self action:#selector(saveTapped:)
forControlEvents:UIControlEventTouchUpInside];
[_editView addSubview: _saveButton];
}
return self;
}
Related
My application starts by showing some Intro slides. 4 in total and in the last one, a button is used to close the slides and to go to the main page.
What I wish to make is to remove the button, and to make the last slide slidable. The user continues to slide to the right, and at the end it lands to the main page.
But don't know how to acheave that.
Here is the definition of
#interface IntroSlideViewController ()<ABCIntroViewDelegate>
#property ABCIntroView *introView;
#end
#implementation IntroSlideViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
-(void)viewDidAppear:(BOOL)animated{
/***************Page Control**************/
self.introView = [[ABCIntroView alloc] initWithFrame:self.view.frame];
self.introView.delegate = self;
self.introView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.000];
[self.view addSubview:self.introView];
/***************************************/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)onDoneButtonPressed {
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:FIRSTTIME_LOGIN];
InitScreenViewController* initVc = [self.storyboard instantiateViewControllerWithIdentifier:#"initScreenViewController"];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:initVc];
[navVC setNavigationBarHidden:true];
[UIView transitionWithView:[AppDelegate getShareInstance].window duration:0.1f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[AppDelegate getShareInstance].window.rootViewController = navVC;
}completion:nil];
}
#end
And the parent class ABCIntroViewDelegate:
#interface ABCIntroView () <UIScrollViewDelegate>
#property (strong, nonatomic) UIScrollView *scrollView;
#property (strong, nonatomic) UIPageControl *pageControl;
#property (strong, nonatomic) UIButton *doneButton;
#property (strong, nonatomic) UIView *viewOne;
#property (strong, nonatomic) UIView *viewTwo;
#property (strong, nonatomic) UIView *viewThree;
#property (strong, nonatomic) UIView *viewFour;
#property (strong, nonatomic) UIView *viewFive;
#end
#implementation ABCIntroView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
[self addSubview:self.scrollView];
[self addSubview:self.pageControl];
[self.scrollView addSubview:self.viewOne];
[self.scrollView addSubview:self.viewTwo];
[self.scrollView addSubview:self.viewThree];
[self.scrollView addSubview:self.viewFour];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
//Done Button
//[self addSubview:self.doneButton];
}
return self;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = CGRectGetWidth(self.bounds);
CGFloat pageFraction = self.scrollView.contentOffset.x / pageWidth;
self.pageControl.currentPage = roundf(pageFraction);
}
-(UIView *)viewOne {
if (!_viewOne) {
_viewOne = [[UIView alloc] initWithFrame:self.frame];
UIImageView *imageview;
imageview = [[UIImageView alloc] initWithFrame:self.frame];
imageview.image = [UIImage imageNamed:#"intro_slide_0"];
[_viewOne addSubview:imageview];
}
return _viewOne;
}
-(UIView *)viewTwo {
if (!_viewTwo) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewTwo = [[UIView alloc] initWithFrame:CGRectMake(originWidth, 0, originWidth, originHeight)];
UIImageView *imageviewTwo;
imageviewTwo = [[UIImageView alloc] initWithFrame:self.frame];
imageviewTwo.image = [UIImage imageNamed:#"intro_slide_1"];
[_viewTwo addSubview:imageviewTwo];
}
return _viewTwo;
}
-(UIView *)viewThree{
if (!_viewThree) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewThree = [[UIView alloc] initWithFrame:CGRectMake(originWidth*2, 0, originWidth, originHeight)];
UIImageView *imageviewThree;
imageviewThree = [[UIImageView alloc] initWithFrame:self.frame];
imageviewThree.image = [UIImage imageNamed:#"intro_slide_2"];
[_viewThree addSubview:imageviewThree];
}
return _viewThree;
}
-(UIView *)viewFour {
if (!_viewFour) {
CGFloat originWidth = self.frame.size.width;
CGFloat originHeight = self.frame.size.height;
_viewFour = [[UIView alloc] initWithFrame:CGRectMake(originWidth*3, 0, originWidth, originHeight)];
UIImageView *imageviewFour;
imageviewFour = [[UIImageView alloc] initWithFrame:self.frame];
imageviewFour.image = [UIImage imageNamed:#"intro_slide_3"];
[_viewFour addSubview:imageviewFour];
UIButton *btnDone = [[UIButton alloc] initWithFrame:CGRectMake(30, self.frame.size.height - 130, self.frame.size.width-60, 50)];
[btnDone setImage:[UIImage imageNamed:#"slide_3_button_unpressed"] forState:UIControlStateNormal];
[btnDone setImage:[UIImage imageNamed:#"slide_3_button_pressed"] forState:UIControlStateHighlighted];
[btnDone addTarget:self.delegate action:#selector(onDoneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_viewFour addSubview:btnDone];
}
return _viewFour;
}
-(UIView *)viewFive {
if (!_viewFive) {
}
return _viewFive;
}
-(UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
[_scrollView setDelegate:self];
[_scrollView setPagingEnabled:YES];
[_scrollView setContentSize:CGSizeMake(self.frame.size.width*numberofPage, self.scrollView.frame.size.height)];
[self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}
return _scrollView;
}
-(UIPageControl *)pageControl {
if (!_pageControl) {
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.frame.size.height-20, self.frame.size.width, 10)];
//[_pageControl setCurrentPageIndicatorTintColor:UIColorFromRGBAlpha(252, 61, 136, 1)];
//[_pageControl setPageIndicatorTintColor:UIColorFromRGBAlpha(223, 227, 232, 1)];
[_pageControl setNumberOfPages:numberofPage];
}
return _pageControl;
}
-(UIButton *)doneButton {
if (!_doneButton) {
_doneButton = [[UIButton alloc] initWithFrame:CGRectMake(0, self.frame.size.height-60, self.frame.size.width, 100)];
[_doneButton setTintColor:[UIColor whiteColor]];
// [_doneButton.titleLabel setFont:FONT_Regular(17)];
[_doneButton setBackgroundColor:[UIColor colorWithRed:96/255.0 green:167/255.0 blue:23/255.0 alpha:1]];
[_doneButton addTarget:self.delegate action:#selector(onDoneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
return _doneButton;
}
#end
Maybe what I am asking is not possible to be implemented.
Any clues and ideas are welcome
You can easily achieve your requirement by modifying ABCIntroView class. From ABCIntroView you are getting the callback as - (void)onDoneButtonPressed to IntroSlideViewController so there you are navigating to MainViewController.
So follow up these steps to achieve your requirement
Remove done button code from ABCIntroView.
Modify the below function.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat pageWidth = CGRectGetWidth(self.bounds);
CGFloat pageFraction = self.scrollView.contentOffset.x/pageWidth;
self.pageControl.currentPage = roundf(pageFraction);
if (self.delegate != nil && self.pageControl.currentPage == 4){
[self.delegate onDoneButtonPressed];
}}
I am trying to programatically setup my UINavigationBar. I have setup the NavBar for each tab in interface builder and it inherits from my GenericTabUiNavBar in interface builder.
However when I run the app, the GenericTabUiNavBar is not loaded with its elements into the UINavBar.
Here is my GenericTabUiNavBar code:
.h
#import <UIKit/UIKit.h>
#interface GenericTabUiNavBar : UINavigationBar
#property (nonatomic, strong) UILabel *firstLetter;
#property (nonatomic, strong) UILabel *secondLetter; //need two labels
#property (nonatomic,strong) UIButton *leftSideButton;
#property (nonatomic,strong) UIButton *rightSideButton;
#end
.m
#implementation GenericTabUiNavBar
#synthesize firstLetter;
#synthesize secondLetter;
#synthesize leftSideButton;
#synthesize rightSideButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code
//r g b
//Yellow Color = 255,219,17
UIColor *yellowColor = [[UIColor alloc] initWithRed:255 green:219 blue:17 alpha:1];
UIColor *blueColor = [[UIColor alloc] initWithRed:1 green:129 blue:200 alpha:1];
UIFont *fontFaceAndSize = [UIFont fontWithName:#"HelveticaNeue" size:36];
//self
self.frame = CGRectMake(0, 20, 320, 44);
self.backgroundColor = blueColor;
self.barTintColor = blueColor;
//x.108 y.31
//w.15 / y.21
CGRect firstLetterRect = CGRectMake(108, 31, 15, 21);
self.firstLetter = [[UILabel alloc] initWithFrame:firstLetterRect];
firstLetter.text = #"An";
firstLetter.font = fontFaceAndSize;
firstLetter.textColor = [UIColor whiteColor];
//128 31
//22 21
CGRect secLetterRect = CGRectMake(108, 31, 15, 21);
self.secondLetter = [[UILabel alloc] initWithFrame:secLetterRect];
secondLetter.text = #"APP";
secondLetter.font = fontFaceAndSize;
secondLetter.textColor = yellowColor;
//tex pos =
self.leftSideButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 29, 30, 26)];
self.rightSideButton = [[UIButton alloc] initWithFrame:CGRectMake(207, 29, 30, 26)];
[leftSideButton setImage:[UIImage imageNamed:#"anImg.png"] forState:UIControlStateNormal];
[rightSideButton setImage:[UIImage imageNamed:#"otherImg.png"] forState:UIControlStateNormal];
[self addSubview:leftSideButton];
[self addSubview:firstLetter];
[self addSubview:secondLetter];
[self addSubview:rightSideButton];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
In my TabViewController I call it by hooking it up in interface builder. Why does this not load?
When controllers are loaded from storyboard or xib. The init method
- (id)initWithCoder:(NSCoder *)decoder
is called instead of the
- (instancetype)initWithNibName:(NSString *)nibName
bundle:(NSBundle *)nibBundle
as for views the reason might be the same
I have a UIVIew with Button. This is loaded in the VIewController as hidden. No problem unhiding it but the button on top of it is not working. Is the UIview class the right place to put the codes for the exit button (hiding it again)?
in .h
#interface infoView : UIView
#property (nonatomic, strong) IBOutlet UIView *infoTextView;
#property (nonatomic, strong) UIButton *exitButton;
-(void)exitView:(UIButton*)sender;
#end
in .m
#import "infoView.h"
#implementation infoView
#synthesize infoTextView = _infoTextView;
#synthesize exitButton=_exitButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_infoTextView = [[UIView alloc]initWithFrame:CGRectMake(40, 40, 240, 240)];
[_infoTextView setBackgroundColor: [UIColor blueColor]];
[self addSubview:_infoTextView];
_exitButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 10, 30, 30)];
//other info
[self.infoTextView addSubview:self.exitButton];
}
return self;
}
-(void)exitView:(UIButton*)sender
{
self.infoTextView.hidden=YES;
}
viewController
#implementation gjViewController
#synthesize imageViewMain = _imageViewMain;
#synthesize changeImageButton = _changeImageButton;
#synthesize infoButton = _infoButton;
#synthesize myInfo = _myInfo;
- (void)viewDidLoad
{
[super viewDidLoad];
_imageViewMain = [[UIImageView alloc] init];
//other info
[self.view addSubview:self.imageViewMain];
_changeImageButton = [[UIButton alloc] initWithFrame:CGRectMake(110, 50, 100, 50)];
//other info
[self.view addSubview:self.changeImageButton];
_infoButton = [[UIButton alloc] initWithFrame:CGRectMake(260, 30, 40, 40)];
//other details
[self.view addSubview: self.infoButton];
the section below is the part where the UIView is loaded. It loads and unhides with the IBAction at the bottom. I think you are pointing that this is wrong, not sure how. Thanks for comments.
_myInfo = [[infoView alloc] init];
[self.view addSubview:_myInfo];
[_myInfo setHidden:YES];
}
-(IBAction)newImage:(UIButton*)sender{
//task
-(IBAction)oldImage:(UIButton*)sender{
//taks
-(IBAction)viewInfo:(UIButton*)sender{ <--- unhides the UIView
[_myInfo setHidden:NO];
I am trying to call another method with Delegate and protocols in my app. I need to send the variable "myData" to another view but for some reasons it doesn't works. I don't know what I am doing wrong with the implementation of delegates and protocols. The delegate never call the action of the protocol.
Sorry I'm new with this.
BLEViewController.h
#import <UIKit/UIKit.h>
#import "BLE.h"
#protocol EnviarDatos <NSObject>
//Metodo que se manda llamar pero se implementa en otra clase
-(void) actualizaDatos:(NSData*)Data;
#end
#interface BLEViewController : UITableViewController <BLEDelegate>
{
//id <EnviarDatos> delegate;
}
#property (nonatomic,assign)id delegate;
#property (nonatomic, retain) NSData *myData;
+ (BLE*) theBLEObject;
- (void) scanForPeripherals;
- (IBAction)connect:(id)sender;
-(void) activaProtocolo;
#end
BLEViewController.m
//
// BLEViewController.m
// DL_RemoteBLE_02
//
// Created by Dave Lichtenstein on 3/16/14.
// Copyright (c) 2014 Dave Lichtenstein. All rights reserved.
//
#import "BLEViewController.h"
static BLE* ble;
static UILabel *statusLabel;
static NSString* connectionStatus = #"Not connected!";
#interface BLEViewController ()
#end
#implementation BLEViewController
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(ble==nil)
{
// Create our Bluetooth Low Energy object
//
ble = [[BLE alloc] init];
[ble controlSetup];
ble.delegate = self;
}
// Create a toolbar at the bottom of the screen to show status text, etc.
//
// get screen size
//
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
CGFloat toolbarHeight = 50.0;
CGFloat labelHeight = 50.0;
if(statusLabel==nil) // only create once
{
// create our status label object
//
statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, screenHeight-toolbarHeight-labelHeight, screenWidth, labelHeight)];
statusLabel.backgroundColor = [UIColor clearColor];
statusLabel.textColor = [UIColor blackColor];
statusLabel.font = [UIFont boldSystemFontOfSize:15];
statusLabel.text = #"Connection Status:";
}
// create a toolbar
//
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,screenHeight-toolbarHeight,screenWidth,toolbarHeight)];
toolbar.tintColor = [UIColor blackColor];
/*UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 150, 20)];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blackColor];
label.font = [UIFont boldSystemFontOfSize:15];
label.text = #"Status:";
UIBarButtonItem *labeltext = [[UIBarButtonItem alloc] initWithCustomView:label];
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"" style:UIBarButtonItemStyleDone target:self action:nil];
NSArray *items = [NSArray arrayWithObjects:statusLabel, nil];
toolbar.items = items;
*/
[self.view addSubview:statusLabel];
[self.view addSubview:toolbar];
// Update our status label
statusLabel.text = connectionStatus;
_myData = [[NSData alloc]init];
delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//-------------------------------------------------------
// methods
/////////////////////////////////////////////////////////
+ (BLE*) theBLEObject
{
return ble;
}
-(void) connectionTimer:(NSTimer *)timer
{
if (ble.peripherals.count > 0)
{
[ble connectPeripheral:[ble.peripherals objectAtIndex:0]];
}
NSLog(#"connectionTimer"); // diag
}
// We call this when the view loads to try to connect to our bluetooth perepheral
//
- (void) scanForPeripherals
{
if (ble.activePeripheral)
if(ble.activePeripheral.state == CBPeripheralStateConnected)
{
statusLabel.text = #"Disconnectng from peripheral...";
[[ble CM] cancelPeripheralConnection:[ble activePeripheral]];
return;
}
if (ble.peripherals)
ble.peripherals = nil;
NSLog(#"scanning...");
statusLabel.text = #"Scanning for peripherals...";
[ble findBLEPeripherals:2];
[NSTimer scheduledTimerWithTimeInterval:(float)2.0 target:self selector:#selector(connectionTimer:) userInfo:nil repeats:NO];
//[indConnecting startAnimating];
}
- (IBAction)connect:(id)sender {
[self scanForPeripherals];
}
///////////////////////////////////////////////////////////
#pragma mark - BLE delegate
///////////////////////////////////////////////////////////
NSTimer *rssiTimer;
// When Connected, this will be called
-(void) bleDidConnect
{
NSLog(#"->Connected");
statusLabel.text = #"Connected!";
connectionStatus = #"Connected!";
// Schedule to read RSSI every 1 sec.
rssiTimer = [NSTimer scheduledTimerWithTimeInterval:(float)1.0 target:self selector:#selector(readRSSITimer:) userInfo:nil repeats:YES];
}
// When RSSI is changed, this will be called
-(void) bleDidUpdateRSSI:(NSNumber *) rssi
{
// Append the rssi value to our status label
//
NSString *temp = [NSString stringWithFormat:#"%# (%#)", connectionStatus, rssi];
statusLabel.text = temp;
}
-(void) readRSSITimer:(NSTimer *)timer
{
[ble readRSSI];
}
// When data is comming, this will be called
-(void) bleDidReceiveData:(unsigned char *)data length:(int)length
{
NSData *d = [NSData dataWithBytes:data length:length];
_myData = [NSData dataWithBytes:data length:length];
NSString *s = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];
NSLog(#"Datos en String %#",s);
//_datosdelegate = self;
//Is anyone listening
if([delegate respondsToSelector:#selector(actualizaDatos:)])
{
//send the delegate function with the amount entered by the user
[delegate actualizaDatos:_myData];
NSLog(#"Entro delegado");
}
}
- (void)bleDidDisconnect
{
NSLog(#"->Disconnected");
connectionStatus = #"Disconnected!";
statusLabel.text = #"Disconnected!";
[rssiTimer invalidate];
}
#end
sevenSegmentsViewController.h
#import <UIKit/UIKit.h>
#import "BLEViewController.h"
#import "BLE.h"
#interface sevenSegmentsViewController : UIViewController<EnviarDatos>{
UIImage *unoON;
UIImage *dosON;
UIImage *tresON;
UIImage *cuatroON;
UIImage *cincoON;
UIImage *seisON;
UIImage *sieteON;
UIImage *unoOFF;
UIImage *dosOFF;
UIImage *tresOFF;
UIImage *cuatroOFF;
UIImage *cincoOFF;
UIImage *seisOFF;
UIImage *sieteOFF;
}
#property (strong, nonatomic) IBOutlet UIImageView *uno;
#property (strong, nonatomic) IBOutlet UIImageView *dos;
#property (strong, nonatomic) IBOutlet UIImageView *tres;
#property (strong, nonatomic) IBOutlet UIImageView *cuatro;
#property (strong, nonatomic) IBOutlet UIImageView *cinco;
#property (strong, nonatomic) IBOutlet UIImageView *seis;
#property (strong, nonatomic) IBOutlet UIImageView *siete;
#end
sevenSegmentsViewController.m
//
// sevenSegmentsViewController.m
// iShield
//
// Created by Victor CarreƱo on 29/03/14.
// Copyright (c) 2014 RedBearLab. All rights reserved.
//
#import "sevenSegmentsViewController.h"
#interface sevenSegmentsViewController ()
#end
#implementation sevenSegmentsViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
unoOFF = [UIImage imageNamed:#"7segnh.png"];
dosOFF = [UIImage imageNamed:#"7segnv.png"];
tresOFF = [UIImage imageNamed:#"7segnv.png"];
cuatroOFF =[UIImage imageNamed:#"7segnh.png"];
cincoOFF = [UIImage imageNamed:#"7segnh.png"];
seisOFF = [UIImage imageNamed:#"7segnv.png"];
sieteOFF = [UIImage imageNamed:#"7segnh.png"];
unoON = [UIImage imageNamed:#"7segvh.png"];
dosON = [UIImage imageNamed:#"7segvv.png"];
tresON = [UIImage imageNamed:#"7segvv.png"];
cuatroON =[UIImage imageNamed:#"7segvh.png"];
cincoON = [UIImage imageNamed:#"7segvh.png"];
seisON = [UIImage imageNamed:#"7segvv.png"];
sieteON = [UIImage imageNamed:#"7segvh.png"];
_uno = [[UIImageView alloc]initWithImage:unoOFF];
_dos = [[UIImageView alloc]initWithImage:dosOFF];
_tres = [[UIImageView alloc]initWithImage:tresOFF];
_cuatro = [[UIImageView alloc]initWithImage:cuatroOFF];
_cinco = [[UIImageView alloc]initWithImage:cincoOFF];
_seis = [[UIImageView alloc]initWithImage:seisOFF];
_siete = [[UIImageView alloc]initWithImage:sieteOFF];
//BLEViewController *myBLE = [[BLEViewController alloc]init];
//BLE *myBLE = [BLEViewController theBLEObject];
//NSLog(#"%#", myBLE.myData);
BLEViewController *myBLE = [[BLEViewController alloc]init];
myBLE.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark Delegado de Actualizar datos
-(void) actualizaDatos :(NSData *)myData{
NSLog(#"Datos recividos");
NSLog(#"Imprimio mi data con exitos %#", myData);
}
#end
In a nutshell, your BLEViewController is setting its delegate property to "self" when I think you want it to get set to an instance of "sevenSegmentsViewController". As a result the "if([delegate respondsToSelector:..." test is failing and you are never hitting the call to actualizaDatos. If you are using protocols correctly, you don't really need to test for "respondsToSelector" because by definition, the delegate must support the protocol.
The compiler and IDE are not showing you the error because you declared the property of the BLEViewController as just type "id" instead of
id<EnviarDatos>
If you fix the property declaration to say that your delegate must support the right protocol, you'll immediately see the errors highlighted.
I'm struggling with a retaining issue between two of my UIViewControllers. The view controllers are never deleted causing my app memory to keep growing memory consumption.
UITitleScreenViewController is my initial view controller. When I go from it to UIChooseAntViewController (a choose player screen) I want to relinquish ownership of UITitleViewController but as you can see in the instruments below the controller is still retained after the transition:
The second image is the retain/release history. All entries prior to #133 were issued on the app startup. I believe #133 and #140 are pairs created by the storyboard segue. So whose responsibility is to issue that extra release to destroy the controller? I tried to set self.view = nil on my willDidDisappear method but no deal.
Not only it is not releasing the controllers but it is creating new instances of them each time a transition. For instance, when I come back from ChooseAnt to Title it creates another instance of UITitleViewController!
Things that are important to say:
1) NSZombies flag is not ticked in the target scheme
2) There are no blocks in my UITitleViewController, and I commented out all blocks in UIChooseAntController. In fact these controllers are very simple. UITitle is entirely defined via storyboard (just a view with a background and two buttons performing segues)
while UIChooseAnt is a control that presents a background and a swipe interface to display available characters and radio buttons. The segue is performed programatically by calling [self performSegueWithIdentifier];
3) I don't know if this matters but the segues are defined as modal and have no animation.
EDIT: 4) None of the the controllers reference each other.
Below is the source code for the TitleViewController
This problem is driving me crazy. If anyone could shed some light on it. Anything would be of great help! Thanks!
#interface SMTitleScreenViewController ()
#property (weak, nonatomic) IBOutlet UIButton *buttonPlay;
#property (weak, nonatomic) IBOutlet UIButton *buttonCamera;
- (IBAction)onButtonPlay:(id)sender;
- (IBAction)onButtonCamera:(id)sender;
#end
#implementation SMTitleScreenViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIColor* color = [UIColor colorWithRed:0.2509f green:0.1176f blue:0.0745f alpha:1.0f];
UIFont* font = [UIFont fontWithName:#"Jungle Roar" size:BUTTON_FONT_SIZE];
NSString* playString = NSLocalizedString(#"Play", #"");
NSString* cameraString = NSLocalizedString(#"Camera", #"");
[self.buttonPlay setTitle:playString forState:UIControlStateNormal];
[self.buttonPlay setTitle:playString forState:UIControlStateHighlighted];
[self.buttonPlay setTitleColor:color forState:UIControlStateNormal];
[self.buttonPlay setTitleColor:color forState:UIControlStateHighlighted];
self.buttonPlay.titleLabel.font = font;
[self.buttonCamera setTitle:cameraString forState:UIControlStateNormal];
[self.buttonCamera setTitle:cameraString forState:UIControlStateHighlighted];
[self.buttonCamera setTitleColor:color forState:UIControlStateNormal];
[self.buttonCamera setTitleColor:color forState:UIControlStateHighlighted];
self.buttonCamera.titleLabel.font = font;
}
- (void) viewDidDisappear:(BOOL)animated
{
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (IBAction)onButtonPlay:(id)sender
{
}
- (IBAction)onButtonCamera:(id)sender
{
}
EDIT: UIChooseAntViewController (as requested)
#interface SMChooseAntViewController ()
#property (strong, nonatomic) UIImageView* rope;
#property (strong, nonatomic) UIImageView* antFrontLayer;
#property (strong, nonatomic) UIImageView* antBackLayer;
#property (strong, nonatomic) NSArray* antFrontImages;
#property (strong, nonatomic) NSArray* antBackImages;
#property (strong, nonatomic) NSArray* antNameImages;
#property (strong, nonatomic) UIButton* leftButton;
#property (strong, nonatomic) UIButton* rightButton;
#property (strong, nonatomic) UIButton* confirmButton;
#property (nonatomic) NSUInteger selectedAntID;
#property (strong, nonatomic) UIImage* radioImageHighlighted;
#property (strong, nonatomic) UIImage* radioImage;
#property (strong, nonatomic) NSMutableArray* radioViews;
#property (weak, nonatomic) IBOutlet UILabel *antDescriptionLabel;
#property (weak, nonatomic) IBOutlet UIImageView *antDescriptionBG;
#property (strong, nonatomic) UIImageView* antNameView;
#property (strong, nonatomic) UISwipeGestureRecognizer* leftSwipeRecognizer;
#property (strong, nonatomic) UISwipeGestureRecognizer* rightSwipeRecognizer;
- (void) onArrowButton:(id)sender;
- (void) onConfirmButton:(id)sender;
- (void) respondToSwipe:(UISwipeGestureRecognizer*)recognizer;
#end
#implementation SMChooseAntViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// Needed to come in between front and back player image layers
UIImage* ropeImage = [UIImage imageNamed:ROPE_IMAGE_PATH];
self.rope = [[UIImageView alloc] initWithImage:ropeImage];
self.rope.center = CGPointMake(screenSize.width / 2.0f, ropeImage.size.height / 2.0f);
UIColor* brownColor = [UIColor colorWithRed:0.2509f green:0.1176f blue:0.0745f alpha:1.0f];
self.antDescriptionLabel.textColor = brownColor;
self.antDescriptionLabel.numberOfLines = 0;
NSArray* antNames = [SMProfile antNames];
// Cache available Player Views in a NSArray
UIImage* frontImages[MAX_AVAILABLE_ANTS];
UIImage* backImages[MAX_AVAILABLE_ANTS];
UIImage* nameImages[MAX_AVAILABLE_ANTS];
for (NSUInteger i = 0; i < MAX_AVAILABLE_ANTS; ++i)
{
NSString* antName = [antNames objectAtIndex:i];
frontImages[i] = [SMImage imageNamed:[NSString stringWithFormat:#"%#_title_front.png", antName]];
backImages[i] = [SMImage imageNamed:[NSString stringWithFormat:#"%#_title_back.png", antName]];
nameImages[i] = [SMImage imageNamed:[NSString stringWithFormat:#"%#_name.png", antName]];
}
self.antFrontImages = [NSArray arrayWithObjects:frontImages[0], frontImages[1], frontImages[2], nil];
self.antBackImages = [NSArray arrayWithObjects:backImages[0], backImages[1], backImages[2], nil];
self.antNameImages = [NSArray arrayWithObjects:nameImages[0], nameImages[1], nameImages[2], nil];
// Load Selected player from profile
SMProfile* profile = [SMProfile mainProfile];
self.selectedAntID = profile.antID.unsignedIntegerValue;
self.antFrontLayer = [[UIImageView alloc] initWithImage:[self.antFrontImages objectAtIndex:self.selectedAntID]];
self.antBackLayer = [[UIImageView alloc] initWithImage:[self.antBackImages objectAtIndex:self.selectedAntID]];
self.antNameView = [[UIImageView alloc] initWithImage:[self.antNameImages objectAtIndex:self.selectedAntID]];
self.antNameView.center = CGPointMake(screenSize.width / 2.0f, self.antDescriptionBG.frame.origin.y);
NSString* antDescriptionKey = [NSString stringWithFormat:#"AntDescription%lu", (unsigned long)self.selectedAntID];
self.antDescriptionLabel.text = NSLocalizedString(antDescriptionKey, #"");
self.antDescriptionLabel.numberOfLines = 0;
self.antDescriptionLabel.adjustsFontSizeToFitWidth = YES;
self.antFrontLayer.center = CGPointMake(screenSize.width / 2.0f, ropeImage.size.height * 0.75f);
self.antBackLayer.center = self.antFrontLayer.center;
// Here a perform button creation, loading and positioning
// No blocks are being called
// add Target to buttons
[self.leftButton addTarget:self action:#selector(onArrowButton:) forControlEvents:UIControlEventTouchUpInside];
[self.rightButton addTarget:self action:#selector(onArrowButton:) forControlEvents:UIControlEventTouchUpInside];
[self.confirmButton addTarget:self action:#selector(onConfirmButton:) forControlEvents:UIControlEventTouchUpInside];
// Create and configure SwipeRecognizers
self.leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(respondToSwipe:)];
self.leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:self.leftSwipeRecognizer];
self.rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(respondToSwipe:)];
self.rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:self.rightSwipeRecognizer];
// Here a create a custom page control scheme. I load two radio button images
// create views and add them to the root view node.
// Add remaining view to the hierarchy
[self.view addSubview:self.antBackLayer];
[self.view addSubview:self.rope];
[self.view addSubview:self.antFrontLayer];
[self.view addSubview:self.confirmButton];
[self.view bringSubviewToFront:self.antDescriptionBG];
[self.view bringSubviewToFront:self.antDescriptionLabel];
[self.view addSubview:self.leftButton];
[self.view addSubview:self.rightButton];
[self.view addSubview:self.antNameView];
[self.view bringSubviewToFront:[self.radioViews objectAtIndex:0]];
}
- (void) viewDidDisappear:(BOOL)animated
{
if ([self.view window] == nil)
{
self.rope = nil;
self.antFrontLayer = nil;
self.antBackLayer = nil;
self.antFrontImages = nil;
self.antBackImages = nil;
self.antNameImages = nil;
self.leftButton = nil;
self.rightButton = nil;
self.confirmButton = nil;
self.radioImageHighlighted = nil;
self.radioImage = nil;
self.radioViews = nil;
self.antNameView = nil;
self.leftSwipeRecognizer = nil;
self.rightSwipeRecognizer = nil;
self.view = nil;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self.view window] == nil)
{
self.view = nil;
}
}
- (void)onArrowButton:(id)sender
{
UIButton* button = (UIButton*)sender;
NSInteger direction = button.tag;
// if on boundaries do nothing (first ant selected and swipe left or last ant selected and swipe right)
if ((self.selectedAntID == 0 && direction == -1) || (self.selectedAntID == (MAX_AVAILABLE_ANTS - 1) && direction == 1))
{
return;
}
// Update Radio Buttons. Unselect previous and select next.
UIImageView* currRadio = [self.radioViews objectAtIndex:self.selectedAntID];
currRadio.image = self.radioImage;
self.selectedAntID = (self.selectedAntID + MAX_AVAILABLE_ANTS + direction) % MAX_AVAILABLE_ANTS;
UIImageView* nextRadio = [self.radioViews objectAtIndex:self.selectedAntID];
nextRadio.image = self.radioImageHighlighted;
self.antFrontLayer.image = [self.antFrontImages objectAtIndex:self.selectedAntID];
self.antBackLayer.image = [self.antBackImages objectAtIndex:self.selectedAntID];
self.antNameView.image = [self.antNameImages objectAtIndex:self.selectedAntID];
// here I was issuing some block to perform the swipe animation for the ant image views. I commented them and I'm just replacing the images now (3 lines above)
}
- (void)onConfirmButton:(id)sender
{
// Save player choice to profile and perform segue
SMProfile* profile = [SMProfile mainProfile];
profile.antID = [NSNumber numberWithUnsignedInt:self.selectedAntID];
[profile save];
[self performSegueWithIdentifier:#"chooseAntToStageSelect" sender:self];
}
- (void) respondToSwipe:(UISwipeGestureRecognizer *)recognizer
{
// forward swipe to onArrowButton message
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft)
{
[self onArrowButton:self.rightButton];
}
else if (recognizer.direction == UISwipeGestureRecognizerDirectionRight)
{
[self onArrowButton:self.leftButton];
}
}
#end
When presenting B view controller from A, A will not release as A is the presentingViewController (please refer to the sdk doc).
Or if A,B are sub view controller of a navigation controller, A is store int he push stack which is not removed when pushing to B.
You are pushing a view controller on to a stack hence until the last one is not popped, the controller will not be released.
To go deep into dependencies on childs read the the article below.
Greatly explained, i am sure it'll help. :)
http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html