custom UISwitch won't change state - iphone

I have a custom uiswitch class, nothing special, the header looks like this:
#import <Foundation/Foundation.h>
#class Course;
#class Student;
#interface AttandanceSwitch : UISwitch
#property (strong,nonatomic) Course *course;
#property (strong,nonatomic) Student *student;
#property (strong,nonatomic) UISwitch *originalSwitch;
-(id)initWithSwitch:(UISwitch *)newSwitch Student:(Student *)student andCourse:(Course *)course;
-(NSString *) description;
#end
the .m file looks as follows:
#import "AttandanceSwitch.h"
#import "Course.h"
#import "Student.h"
#implementation AttandanceSwitch
#synthesize course,student,originalSwitch;
-(id)initWithSwitch:(UISwitch *)newSwitch Student:(Student *)studentP andCourse:(Course *)courseP
{
self = [super init];
self.course = courseP;
self.student = studentP;
self.originalSwitch = newSwitch;
[self.originalSwitch setOn:YES];
return self;
}
-(NSString *) description
{
return [NSString stringWithFormat:#"Student: %#, Course: %#, Switch: %#",student.name,course.name,[originalSwitch description]];
}
#end
So whats actually the problem - when I create a new object of this class using initWithSwitch, I cant set the originalSwitch value. I even tried to set it statically (see self.originalSwitch setOn:YES above), but even if I do that, the switch is still off.
Any ideas on how to get this working would be very appreciated...
this is a excerpt from usage of this class in tableviewcell:
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
[switchView addTarget:self action:#selector(valueChanged:) forControlEvents:UIControlEventTouchUpInside];
AttandanceSwitch *customSwitch = [[AttandanceSwitch alloc] initWithSwitch:switchView Student:student andCourse:courseToTrack];
Student and Course get filled allright.

Your code will work if you call it like this in your ViewController's viewDidLoad:
UISwitch *newSwitch = [[UISwitch alloc] init];
AttandanceSwitch *customSwitch = [[AttandanceSwitch alloc] initWithSwitch:newSwitch];
[self.view addSubView:customSwitch.original];
[customSwitch.original setOn:YES];

Related

Issue with UIButton Subclass delegate method

Here is the situation. I have a view controller titled "MyViewController." Within this view controller I have a text editing feature that uses subclassed buttons. The name of the UIButton Subclass is "ColorSwatch"
I have setup delegate/protocol methods in the "ColorSwatch.h" subclass as follow.
// ColorSwatch.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#protocol ColorSwatchDelegate <NSObject>
- (void)fontColor:(UIColor *)color;
#end
#interface ColorSwatch : UIButton {
id <ColorSwatchDelegate> colorSwatchDelegate;
CAGradientLayer *gradient;
UIView *currentView;
UIColor *fontColor;
}
#property (nonatomic, retain) id <ColorSwatchDelegate> colorSwatchDelegate;
#property (nonatomic, retain) CAGradientLayer *gradient;
#property (nonatomic, retain) UIView *currentView;
#property (nonatomic, retain) UIColor *fontColor;
#end
Now in my "ColorSwatch.m" I have:
// ColorSwatch.m
#import "ColorSwatch.h"
#import <QuartzCore/QuartzCore.h>
#import "MyViewController.h"
#implementation ColorSwatch
#synthesize gradient;
#synthesize currentView;
#synthesize colorSwatchDelegate;
#synthesize fontColor;
-(void)setupView{
"Makes the subclassed buttons pretty"
}
-(id)initWithFrame:(CGRect)frame{
if((self = [super initWithFrame:frame])){
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
if((self = [super initWithCoder:aDecoder])){
[self setupView];
MyViewController *mvc = [[MyViewController alloc] initWithNibName:
#"MyViewController" bundle:nil];
self.colorSwatchDelegate = mvc;
}
return self;
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self magnify:view];
fontColor = view.backgroundColor;
[self.colorSwatchDelegate fontColor:fontColor];
}
- (void)magnify:(UIView *)view
{
}
- (void)dealloc
{
[currentView release];
[gradient release];
[fontColor release];
[super dealloc];
}
#end
In the "MyViewController.h" I have:
// MyViewController.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ColorSwatch.h"
#interface MyViewController : UIViewController <ColorSwatchDelegate> {
UITextField *photoLabelTextField;
}
#property (nonatomic, retain) IBOutlet UITextField *photoLabelTextField;
#end
In the "MyViewController.m" I have:
- (void)fontColor:(UIColor *)color
{
NSLog(#"Selected Font Color");
[self.photoLabelTextField setTextColor:color];
}
Now the delegate method sort of works, meaning when I tap on a color button the
NSLog(#"Selected Font Color");
message gets fired. But the problem is that I cannot change the
[self.photoLabelTextField setTextColor:color];
property. I have tried numerous ways of changing the property, the only thing that I can do is send NSLogs, anything I try to change a property in the "MyViewController" Class nothing happens.
If anyone could please help me out, I would appreciate it.
Thank you
The problem is that the ColorSwatch is sending delegate messages to a dangling instance of MyViewController that it incorrectly allocated in it's initWithCoder: method.
UIControls shouldn't allocate ViewControllers to be their delegates... it goes the other way around.
Delete these lines...
// in ColorSwatch.m initWithCoder:
MyViewController *mvc = [[MyViewController alloc] initWithNibName:
#"MyViewController" bundle:nil];
self.colorSwatchDelegate = mvc;
Then, in MyViewController.m ...
- (void)viewDidLoad {
ColorSwatch *colorSwatchButton = [[ColorSwatch alloc] buttonWithType:UIButtonTypeCustom];
// or place a ColorSwatch in the xib, on MyViewController's view... But not before you
// you delete lines from initWithCoder, otherwise it's infinite circular allocation
colorSwatchButton.frame = CGRectMake(/* ... */);
colorSwatchButton addTarget:self action:#selector(csButtonPressed:) forControlEvent: UIControlEventTouchUpInside];
// and so on...
// now the important part:
colorSwatchButton.colorSwatchDelegate = self;
// see - the ViewController is in charge of allocation, sets itself up as the delegate
[self.view addSubview:colorSwatchButton];
}
Instead of building the button in code, you can use IB.
Step 1: make the delegate an outlet...
#property (nonatomic, retain) IBOutlet id <ColorSwatchDelegate> colorSwatchDelegate;
Step 2: draw the buttons in IB, and set their class to ColorSwatch.
Then you can skip the code I wrote in viewDidLoad.
Step 3: The newly placed button should now present an outlet in IB. You can drag from that to the MyViewController as you normally do.
There might be a connection problem in your IBOutlet photoLabelTextField, you may have forgotten to connect xib text field with your photoLabelTextField

Copy of string from one view to another view in iphone

hi i am new to iphone development.
I'm trying with sample where I need to copy a string from the textfield of viewController and display it on the next view with a Label.
On the first view there is button bellow the textfield.1
I am not able to fix some issues showing BAD ACESS can anyone help me in solving this.
Let me know what i'm doing Wrong.
Thank you.
//copystring.h
#interface CopystringViewController : UIViewController{
UITextField *myTextField;
NSString *somestring;
}
#property(nonatomic,retain)IBOutlet UITextField *myTextfield;
#property(nonatomic,retain)NSString *somestring;
-(IBAction)next:(id)sender;
//.m file
#synthesize myTextfield,somestring;
-(IBAction)next:(id)sender;
{
NextView * next = [[NextView alloc] initWithNewString: myTextField.text];
[self.navigationController presentModalViewController: next animated: YES];
}
NextView.h
#interface NextView : UIViewController{
UILabel *string2;
}
#property(nonatomic,retain)IBOutlet UILabel *string2;
- (id)initWithNewString:(NSString*)someString;
//.m file
#synthesize string2;
-(id)initWithNewString:(NSString*)someString {
string2 = someString;
return self;
}
Just replace method.it may run.
-(IBAction)next:(id)sender; {
NextView * next = [[NextView alloc] initWithNibName:#"NextView" bundle:nil];
next.string2=myTextField.text;
[self.navigationController presentModalViewController:next animated: YES];
}
hey string2 is a label so try string2.text = somestring;
-(id)initWithNewString:(NSString*)someString {
string2.text = someString;
return self;
}
It looks like the problem is that you're assigning an NSString (someString) to a UILabel (string2).
AppleVijay's answer should do the trick.
If you don't like dot-notation in ObjC you can also write it like this:
[string2 setText:someString]
U can declare ur somestring in to the delagate h/m file that way it wil be the global string. u can use it with appdaligateobj.stringname.
U dont evn need init u can directly add to viewdidload of next view.
string2.text = AppDalegateobj.stringName.
Delegation is the usual way to move data around like this. I wrote a very simple example project to show this in action.
You need init you view and retain you string:
-(id)initWithNewString:(NSString*)someString {
self = [super init];
if (self) {
string2.text = someString;
}
return self;
}
/
/AppDelegate.h
NSString *String1;
#property (nonatomic, retain) NSString * String1;
//AppDelegate.m
#synthesize String1
//ViewController1.h
AppDelegate * objAppDelegate;
UILable *lblstring;
#property (nonatomic, retain) UILable *lblstring;
//ViewController1.m
#synthesize lblstring
//On View Did Load.
objAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
lblstring.text = objAppDelegate.String1;

Subclassed controls not being released

We have found a large memory issue in our application. We have subclassed UITextField and add these to all of our main views. The main views are being dealloced correctly, however the dealloc method in our subclass never gets hit. Here is our subclass:
Header:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "MyEntities.h"
#import "MyControlHelper.h"
#interface MyTextField : UITextField {
MyControlHelper *myHelper;
UIView *disabledEffect;
}
#property (nonatomic, retain) MyControlHelper *myHelper;
#property (nonatomic, retain) UIView *disabledEffect;
#end
Implementation:
#import "MyTextField.h"
#implementation MyTextField
#synthesize myHelper;
#synthesize disabledEffect;
-(id) initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(id) init{
if (self = [super init]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(id)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(void)dealloc{
self.myHelper = nil;
self.disabledEffect= nil;
[super dealloc];
}
#end
Any help would be greatly appreciated.
Cheers.
You might have an issue with your myHelper reference. You have declared it as (nonatomic, retain) property. If your MyControlHelper class has a property for your MyTextField also being retained, you are building a cyclic reference and your field is retaining myHelper and vice versa.
If this is the case I suggest you declare the property for the textfield within MyControlHelper with (nonatomic, assign) to resolve the cycle.
It would help to post the code for MyControlHelper, as well.

Adding stuff to UIView from other class

It's a very simple question, but I don't get it to work properly. I have the following setup:
iPhone app with a main controller (ViewController). I thought it would be better to export some parts of it to new files (better structure etc). So I created a new class, "ClassFile". This is what I want to do:
ViewController.m
// Launch function from other ViewController class
-(void)someWhereAtViewController {
ClassFile *Classinstance = [[ClassFile alloc] init];
UILabel *label = [Classinstance createLabel];
[Classinstance release];
}
ClassFile.m
// Do some stuff
-(UILabel *)createLabel {
// Create an UILabel "label"
[...]
// Now add the label to the main view
// Like this it clearly doesn't work, but how to do it?
[self.view addSubview:label]
// Return the label to the other class
return label
}
Thanks a lot for the input! As far as I know, everything in this dummycode works except adding the label to the main view.
-(UILabel *)createLabelInView: (UIView *)view {
// Create an UILabel "label"
[...]
// Now add the label to the main view
// Like this it clearly doesn't work, but how to do it?
[view addSubview:label]
// Return the label to the other class
return label
}
and then call it with:
// Launch function from other ViewController class
-(void)someWhereAtViewController {
ClassFile *Classinstance = [[ClassFile alloc] init];
UILabel *label = [Classinstance createLabelInView: self.view];
[Classinstance release];
}
It sounds like you want a "Category". A category is a way to add methods to existing classes, regardless of whether you have their source code or not.
So you have:
//ViewController.h
#interface ViewController : UIViewController {
}
#end
//ViewController.m
#import "ViewController.h"
#implementation ViewController
...
#end
You want another file with more methods for ViewController, correct? If so, then you'd do:
//ViewController+Extras.h
#import "ViewController.h"
#interface ViewController (Extras)
- (UILabel *)createLabel;
#end
//ViewController+Extras.m
#import "ViewController+Extras.h"
#implementation ViewController (Extras)
- (UILabel *)createLabel {
return [[[UILabel alloc] initWithFrame:CGRectMake(0,0,42,42)] autorelease];
}
#end
And then you'll be able to do:
//ViewController.m
#import "ViewController.h"
#import "ViewController+Extras.h"
#implementation ViewController
- (void)doStuff {
UILabel *newLabel = [self createLabel];
//do stuff
}
#end
For more information on Categories, check out the Documentation.

iphone - passing an object on an UIToolbarButton action

Is that possible to make a UIToolbarButton pass an object to its target by using some exoteric method (as it seems not to be possible using regular button use)?
I mean something like
UIBarButtonItem *Button = [[UIBarButtonItem alloc] initWithImage:buttonImage
style:UIBarButtonItemStylePlain target:self action:#selector(doSomething:) **withObject:usingThis**];
I know I can trigger a method that will launch the full method with the object, but for the sake of elegance I was trying to minimize the code... I suspect it is not possible, but as you guys out there are insanely good you may come with an transcendental answer... who knows...
You would have to extend the UIBarButtonItem class.
Here is an example creating RCBarButtonItem class. I've used initWithTitle for ease, I'm sure you could change it...
The UIBarButtonItem Subclass
#import <UIKit/UIKit.h>
#interface RCBarButtonItem : UIBarButtonItem {
id anObject;
}
#property (nonatomic, retain) id anObject;
- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action withObject:(id)obj;
#end
#implementation RCBarButtonItem
#synthesize anObject;
-(void)dealloc {
[anObject release];
[super dealloc];
}
- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action withObject:(id)obj {
if (self = [super initWithTitle:title style:style target:target action:action]) {
self.anObject = obj;
}
return self;
}
#end
Then this could then be implemented like so:
#import "RootViewController.h"
#import "RCBarButtonItem.h"
#implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
RCBarButtonItem *button = [[RCBarButtonItem alloc] initWithTitle:#"Hello"
style:UIBarButtonItemStylePlain
target:self
action:#selector(doSomething:)
withObject:#"Bye"];
self.navigationItem.rightBarButtonItem = button;
}
- (void)doSomething:(id)sender {
NSLog(#"%#", [(RCBarButtonItem *)sender anObject]);
}
What I've done in this situation is create an NSDictionary property called, say, buttonArguments:
self. buttonArguments = [[NSDictionary alloc] initWithObjectsAndKeys: usingThis, Button, ... , nil];
Then in your doSomething: method, look up the object based on the sender parameter.
I prefer using categories:
UIBarButtonItem+BarButtonItem.h
#interface UIBarButtonItem (BarButtonItem)
#property (strong, nonatomic) NSDictionary *userInfo;
#end
UIBarButtonItem+BarButtonItem.m
static void *kUserInfo = &kUserInfo;
#implementation UIBarButtonItem (BarButtonItem)
- (NSDictionary *)userInfo {
return objc_getAssociatedObject(self, kUserInfo);
}
- (void)setUserInfo:(NSDictionary *)userInfo {
objc_setAssociatedObject(self, kUserInfo, userInfo,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end