Changing label text on SKLabelNode crashes app - ios

I'm trying to change the text in a SKLabelNode at runtime but it crashes the app with an error: CRASH: -[SKLabelNode label]: unrecognized selector sent to instance
I'm calling it from a selectNodeForTouch:(CGPoint)touchlocation method as follows:
if ([[node name]isEqualToString:#"e"]) {
// add current riddle to favourites and change the icon of the star
button *btn = (button *)[self nodeAtPoint:touchLocation];
btn.label.text = #"d";
[(GameViewController *)self.view.window.rootViewController addToFavourites:_currentTomhais];
NSLog(#"Favourited");
}
The button object has the following interface:
#interface button : SKSpriteNode
#property (nonatomic, retain) SKLabelNode *label;
And is initialised as followed in the button.m file
#implementation button
-(instancetype) initWithString:(NSString *)character fontNamed:(NSString *)font size:(float)size{
self = [super init];
if (self) {
[self setSize:CGSizeMake(size, size)];
//icon Text
_label = [[SKLabelNode alloc] initWithFontNamed:font];
_label.name = character;
_label.fontSize = size;
_label.fontColor = [UIColor colorWithRed:150.0f/255.0f
green:166.0f/255.0f
blue:173.0f/255.0f
alpha:1];
[_label setText:character];
_label.position = CGPointMake(0, 0);
[self addChild:_label];
}
return self;
}
Any idea how to change the text on this item at runtime without crashing the app?

You are sending the selector "label" to an SKLabelNode, which doesn't recognize it. The touched node is actually an SkLabelNode, and so you are sending "label" to an SkLabelNode when you are trying to set the text at btn.label.text = #"d";

Related

How to get custom TableViewCell value on view controller without using button and set it after reload table in objective c

I am new in iOS and I am facing problem regarding to get the value from custom table view cell to view controller. I am using rate view for rating and I am checking if value of rate is less then 3 then it show have to enter text in the text view and I want to get value in view controller
My code is like this
CustomTableviewcell.h
#interface NextTableview : UITableViewCell<RateViewDelegate,UITextViewDelegate>
{
NSString *StatusValue;
UILabel *lbl;
}
#property(nonatomic,strong) IBOutlet UILabel *staticlbl;
#property(nonatomic,strong) IBOutlet UITextView *commenttxtview;
#property(nonatomic,strong) IBOutlet UILabel *Kpiidlbl;
#property (weak, nonatomic) IBOutlet RateView *rateView;
#property (weak, nonatomic) IBOutlet UILabel *statusLabel;
#end
CustomTableviewcell.m
#synthesize rateView,staticlbl,statusLabel,commenttxtview,Kpiidlbl;
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
commenttxtview.layer.borderWidth = 0.70f;
commenttxtview.layer.borderColor = [[UIColor blackColor] CGColor];
commenttxtview.delegate=self;
UIToolbar* doneToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
doneToolbar.barStyle = UIBarStyleBlackTranslucent;
doneToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneButtonClickedDismissKeyboard)],
nil];
[doneToolbar sizeToFit];
commenttxtview.inputAccessoryView = doneToolbar;
lbl = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0,90.0, 34.0)];
[lbl setText:#"Enter Text"];
[lbl setFont:[UIFont systemFontOfSize:12]];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor lightGrayColor]];
commenttxtview.delegate = self;
[commenttxtview addSubview:lbl];
statusLabel.hidden=YES;
commenttxtview.hidden=YES;
// Do any additional setup after loading the view from its nib.
self.rateView.notSelectedImage = [UIImage imageNamed:#"not_selected_star#2x.png"];
self.rateView.halfSelectedImage = [UIImage imageNamed:#"half_selected_star#2x.png"];
self.rateView.fullSelectedImage = [UIImage imageNamed:#"selected_star#2x.png"];
self.rateView.rating = 0;
self.rateView.editable = YES;
self.rateView.maxRating = 5;
self.rateView.delegate = self;
Kpiidlbl.hidden=YES;
}
-(void)doneButtonClickedDismissKeyboard
{
[commenttxtview resignFirstResponder];
// commenttxtview.hidden=YES;
}
- (void)textViewDidEndEditing:(UITextView *)theTextView
{
if (![commenttxtview hasText]) {
lbl.hidden = NO;
}
}
- (void) textViewDidChange:(UITextView *)textView
{
if(![commenttxtview hasText]) {
lbl.hidden = NO;
}
else{
lbl.hidden = YES;
}
}
- (void)rateView:(RateView *)rateView ratingDidChange:(int)rating {
self.statusLabel.text = [NSString stringWithFormat:#"%d", rating];
NSLog(#"Rating value =%#",self.statusLabel.text);
StatusValue=statusLabel.text;
NSLog(#"Status Value String =%#",StatusValue);
// Hear I am getting value of rating..in StatusValue..
int status=[StatusValue intValue];
if(status<=3)
{
commenttxtview.hidden=NO;
}
else{
commenttxtview.hidden=YES;
}
}
How can I get label and textview value in viewcontroller and I want to set rate view value to rate view after reload table.
Hear in the Image i am getting five star and If I click on less then 3 star it should have to write comment.I am taking rate value in the label.How can I get both label and textvalue in view controller.Please tell me to update question if you want more data.Thanks in Advance!
So write this in your CustomTableViewCell.h
#property(nonatomic,assign)NSInteger selectedRating;
everytime when the rating is updated in the Cell, you have to change the value of this variable.
In the viewController it depends on when you want to get the value of this cell. For example in this method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
CustomTableViewCell *yourCell = (CustomerTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
NSLog(#"%lu",yourCell.selectedRating);
}
Let me know if this was helpful!
Another way without a variable is to read the NSString in the statusLabel and change the string to a NSInteger variable...
If you are using your delegate...
Then implement the delegate RateViewDelegatein the viewController. The delegate is called in the class to which it is assigned...
Try this
You have to add the #property (nonatomic, weak) NSObject<RateViewDelegate>* delegate;
to the header file of your CustomTableViewCell.h in the method
-(UITableViewCell) cellForRowAtIndexPath....
you have to assign the delegate like this
cell.delegate = self;
Now modify your cell delegate method to this
- (void)rateView:(RateView *)rateView ratingDidChange:(int)rating {
self.statusLabel.text = [NSString stringWithFormat:#"%d", rating];
NSLog(#"Rating value =%#",self.statusLabel.text);
StatusValue=statusLabel.text;
NSLog(#"Status Value String =%#",StatusValue);
// Hear I am getting value of rating..in StatusValue..
int status=[StatusValue intValue];
if(status<=3)
{
commenttxtview.hidden=NO;
}
else{
commenttxtview.hidden=YES;
}
if([self.delegate respondsToSelector:#selector(rateView:ratingDidChange:)]){
[self.delegate rateView:rateView ratingDidChange:rating];
}
}

Unable to configure voice over accessibility for a custom UITableViewCell

Our iPhone app currently supports IOS 8/9/10. I am having difficulty supporting voice over accessibility for a custom UITableViewCell. I have gone through the following SO posts, but none of the suggestions have worked. I want individual components to be accessible.
Custom UITableview cell accessibility not working correctly
Custom UITableViewCell trouble with UIAccessibility elements
Accessibility in custom drawn UITableViewCell
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Making_Application_Accessible/Making_Application_Accessible.html#//apple_ref/doc/uid/TP40008785-CH102-SW10
http://useyourloaf.com/blog/voiceover-accessibility/
Unfortunately for me, the cell is not detected by the accessibility inspector. Is there a way to voice over accessibility to pick up individual elements within the table view cell? When debugging this issue on both device and a simulator, I found that the XCode calls isAccessibleElement function. When the function returns NO, then the rest of the methods are skipped. I am testing on IOS 9.3 in XCode.
My custom table view cell consists of a label and a switch as shown below.
The label is added to the content view, while the switch is added to a custom accessory view.
The interface definition is given below
#interface MyCustomTableViewCell : UITableViewCell
///Designated initializer
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier;
///Property that determines if the switch displayed in the cell is ON or OFF.
#property (nonatomic, assign) BOOL switchIsOn;
///The label to be displayed for the alert
#property (nonatomic, strong) UILabel *alertLabel;
#property (nonatomic, strong) UISwitch *switch;
#pragma mark - Accessibility
// Used for setting up accessibility values. This is used to generate accessibility labels of
// individual elements.
#property (nonatomic, strong) NSString* accessibilityPrefix;
-(void)setAlertHTMLText:(NSString*)title;
#end
The implementation block is given below
#interface MyCustomTableViewCell()
#property (nonatomic, strong) UIView *customAccessoryView;
#property (nonatomic, strong) NSString *alertTextString;
#property (nonatomic, strong) NSMutableArray* accessibleElements;
#end
#implementation MyCustomTableViewCell
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if(self = [super initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:reuseIdentifier]) {
[self configureTableCell];
}
return self;
}
- (void)configureTableCell
{
if (!_accessibleElements) {
_accessibleElements = [[NSMutableArray alloc] init];
}
//Alert label
self.alertLabel = [[self class] makeAlertLabel];
[self.contentView setIsAccessibilityElement:YES];
//
[self.contentView addSubview:self.alertLabel];
// Custom AccessoryView for easy styling.
self.customAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
[self.customAccessoryView setIsAccessibilityElement:YES];
[self.contentView addSubview:self.customAccessoryView];
//switch
self.switch = [[BAUISwitch alloc] initWithFrame:CGRectZero];
[self.switch addTarget:self action:#selector(switchWasFlipped:) forControlEvents:UIControlEventValueChanged];
[self.switch setIsAccessibilityElement:YES];
[self.switch setAccessibilityTraits:UIAccessibilityTraitButton];
[self.switch setAccessibilityLabel:#""];
[self.switch setAccessibilityHint:#""];
self.switch.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.customAccessoryView addSubview:self.switch];
}
+ (UILabel *)makeAlertLabel
{
UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectZero];
alertLabel.backgroundColor = [UIColor clearColor];
alertLabel.HTMLText = #"";
alertLabel.numberOfLines = 0;
alertLabel.lineBreakMode = LINE_BREAK_WORD_WRAP
[alertLabel setIsAccessibilityElement:YES];
return alertLabel;
}
-(void)setAlertHTMLText:(NSString*)title{
_alertTextString = [NSString stringWithString:title];
[self.alertLabel setText:_alertTextString];
}
- (BOOL)isAccessibilityElement {
return NO;
}
// The view encapsulates the following elements for the purposes of
// accessibility.
-(NSArray*) accessibleElements {
if (_accessibleElements && [_accessibleElements count] > 0) {
[_accessibleElements removeAllObjects];
}
// Fetch a new copy as the values may have changed.
_accessibleElements = [[NSMutableArray alloc] init];
UIAccessibilityElement* alertLabelElement =
[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
//alertLabelElement.accessibilityFrame = [self convertRect:self.contentView.frame toView:nil];
alertLabelElement.accessibilityLabel = _alertTextString;
alertLabelElement.accessibilityTraits = UIAccessibilityTraitStaticText;
[_accessibleElements addObject:alertLabelElement];
UIAccessibilityElement* switchElement =
[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
// switchElement.accessibilityFrame = [self convertRect:self.customAccessoryView.frame toView:nil];
switchElement.accessibilityTraits = UIAccessibilityTraitButton;
// If you want custom values, just override it in the invoking function.
NSMutableString* accessibilityString =
[NSMutableString stringWithString:self.accessibilityPrefix];
[accessibilityString appendString:#" Switch "];
if (self.switchh.isOn) {
[accessibilityString appendString:#"On"];
} else {
[accessibilityString appendString:#"Off"];
}
switchElement.accessibilityLabel = [accessibilityString copy];
[_accessibleElements addObject:switchElement];
}
return _accessibleElements;
}
// In case accessibleElements is not initialized.
- (void) initializeAccessibleElements {
_accessibleElements = [self accessibleElements];
}
- (NSInteger)accessibilityElementCount
{
return [_accessibleElements count]
}
- (id)accessibilityElementAtIndex:(NSInteger)index
{
[self initializeAccessibleElements];
return [_accessibleElements objectAtIndex:index];
}
- (NSInteger)indexOfAccessibilityElement:(id)element
{
[self initializeAccessibleElements];
return [_accessibleElements indexOfObject:element];
}
#end
First of all, from the pattern you described, I'm not sure why you would want to differentiate between different elements in a cell. Generally, Apple keeps every cell a single accessibility element. A great place to see the expected iOS VO behavior for cells with labels and switches is in Settings App.
If you still believe the best way to handle your cells is to make them contain individual elements, then that is actually the default behavior of a cell when the UITableViewCell itself does not have an accessibility label. So, I've modified your code below and run it on my iOS device (running 9.3) and it works as you described you would like.
You'll notice a few things.
I deleted all the custom accessibilityElements code. It is not necessary.
I deleted the override of isAccessibilityElement on the UITableViewCell subclass itself. We want default behavior.
I commented out setting the content view as an accessibilityElement -- we want that to be NO so that the tree-builder looks inside of it for elements.
I set customAccessoryView's isAccessibilityElement to NO as well for the same reason as above. Generally, NO says "keep looking down the tree" and YES says "stop here, this is my leaf as far as accessibility is concerned."
I hope this is helpful. Once again, I do really encourage you to mimic Apple's VO patterns when designing for Accessibility. I think it's awesome that you're making sure your app is accessible!
#import "MyCustomTableViewCell.h"
#interface MyCustomTableViewCell()
#property (nonatomic, strong) UIView *customAccessoryView;
#property (nonatomic, strong) NSString *alertTextString;
#property (nonatomic, strong) NSMutableArray* accessibleElements;
#end
#implementation MyCustomTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if(self = [super initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:reuseIdentifier]) {
[self configureTableCell];
}
return self;
}
// just added this here to get the cell to lay out for myself
- (void)layoutSubviews {
[super layoutSubviews];
const CGFloat margin = 8;
CGRect b = self.bounds;
CGSize labelSize = [self.alertLabel sizeThatFits:b.size];
CGFloat maxX = CGRectGetMaxX(b);
self.alertLabel.frame = CGRectMake(margin, margin, labelSize.width, labelSize.height);
CGSize switchSize = [self.mySwitch sizeThatFits:b.size];
self.customAccessoryView.frame = CGRectMake(maxX - switchSize.width - margin * 2, b.origin.y + margin, switchSize.width + margin * 2, switchSize.height);
self.mySwitch.frame = CGRectMake(margin, 0, switchSize.width, switchSize.height);
}
- (void)configureTableCell
{
//Alert label
self.alertLabel = [[self class] makeAlertLabel];
//[self.contentView setIsAccessibilityElement:YES];
//
[self.contentView addSubview:self.alertLabel];
// Custom AccessoryView for easy styling.
self.customAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
[self.customAccessoryView setIsAccessibilityElement:NO]; // Setting this to NO tells the the hierarchy builder to look inside
[self.contentView addSubview:self.customAccessoryView];
self.customAccessoryView.backgroundColor = [UIColor purpleColor];
//switch
self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
//[self.mySwitch addTarget:self action:#selector(switchWasFlipped:) forControlEvents:UIControlEventValueChanged];
[self.mySwitch setIsAccessibilityElement:YES]; // This is default behavior
[self.mySwitch setAccessibilityTraits:UIAccessibilityTraitButton]; // No tsure why this is here
[self.mySwitch setAccessibilityLabel:#"my swich"];
[self.mySwitch setAccessibilityHint:#"Tap to do something."];
self.mySwitch.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.customAccessoryView addSubview:self.mySwitch];
}
+ (UILabel *)makeAlertLabel
{
UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectZero];
alertLabel.backgroundColor = [UIColor clearColor];
alertLabel.text = #"";
alertLabel.numberOfLines = 0;
[alertLabel setIsAccessibilityElement:YES];
return alertLabel;
}
-(void)setAlertHTMLText:(NSString*)title{
_alertTextString = [NSString stringWithString:title];
[self.alertLabel setText:_alertTextString];
}
#end

Store values from UITextFields in NSArray programmatically iOS

I would like to start by saying that I am fairly new to iOS programming, so excuse my ignorance.
I have three UITextFields in my CustomLayout. I am asking users to fill in their name, age and sex. I would like two things, if possible. First I would like, as soon as a user hits the return button from the keyboard, the input string to be stored in an NSArray. In addition, the secondary objective is to iterate through the UITextFields when the user hits the same button.
// CustomLayout.h
#interface CustomLayout : UIView {
UITextField *nameField;
UITextField *ageField;
UITextField *sexField;
UILabel *nameLabel;
UILabel *ageLabel;
UILabel *sexLabel;
UIButton *startButton;
}
#property (nonatomic, strong) UITextField *nameField;
#property (nonatomic, strong) UITextField *ageField;
#property (nonatomic, strong) UITextField *sexField;
#property (nonatomic, strong) UILabel *nameLabel;
#property (nonatomic, strong) UILabel *ageLabel;
#property (nonatomic, strong) UILabel *sexLabel;
#property (nonatomic, strong) UIButton *startButton;
-(void)textFieldShouldReturn:(UITextField*)textField;
#end
In the implementation file
//CustomLayout.m
#implementation CustomLayout
#synthesize nameField, ageField, sexField;
#synthesize nameLabel, ageLabel, sexLabel;
#synthesize startButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[tkStyle viewBackgroundColor]];
NSString *startButtonLabel = #"Start Experiment";
//alocate and position views
CGRect viewRect;//placeholder rect, reused for each view
//nameLabel and nameField
nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(120, 95, 150, 40)];
nameLabel.textColor = [UIColor colorWithRed:106/256.0 green:180/256.0 blue:150/256.0 alpha:1.0];
nameLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
nameLabel.backgroundColor=[tkStyle viewBackgroundColor];
nameLabel.text=#"Enter Name:";
nameField = [[UITextField alloc] initWithFrame:CGRectMake(280, 90, 200, 40)];
nameField.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
nameField.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
nameField.borderStyle = UITextBorderStyleRoundedRect;
nameField.backgroundColor=[tkStyle viewBackgroundColor];
textFieldShouldReturn:nameField.text;
// same for ageField and sexField
//startButton
viewRect = CGRectMake(250, sexField.frame.origin.y+75, 200, 40);
startButton = [[UIButton alloc] initWithFrame:viewRect];
[startButton setTitle:startButtonLabel forState:UIControlStateNormal];
[startButton setTitleEdgeInsets:UIEdgeInsetsMake(4, 0, 0, 0)];
[startButton setButtonIsActive:true];
//[startButton setOSCAddress:OSCStopPressedString];
[startButton addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
//and so on adjust your view size according to your needs
[self addSubview:nameField];
[self addSubview:ageField];
[self addSubview:sexField];
[self addSubview:nameLabel];
[self addSubview:ageLabel];
[self addSubview:sexLabel];
[self addSubview:startButton];
}
return self;
}
// that should allow for users to hit 'return' button to move through textfields
-(void)textFieldShouldReturn:(UITextField*)textField;
{
//[(NSArray *) userInfoArray addObject:textField.text];
}
// that should change Views as soon as the user presses 'Start Experiment'
-(void)buttonAction:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"startTest" object:self];
}
#end
Any help would be appreciated.
NSDictionary will be a good approach. you can have unique key for each textfield value.
-(void)textFieldShouldReturn:(UITextField*)textField;
should be:
- (BOOL)textFieldShouldReturn:(UITextField*)textField;
Also, don't forget to return TRUE or FALSE (or YES or NO).
To make this work, implement the UITextFieldDelegate protocol in your class.
Put the following line of code in your .m file, above the #implementation:
#interface CustomLayout () <UITextFieldDelegate>
#end
then, set the delegate in your UITextFields with:
nameField.delegate = self;
ageField.delegate = self;
sexField.delegate = self;
This way the textFieldShouldReturn: method will be called when the user presses 'enter'
A couple of things:
Given your delegate methods, I assume you've actually specified the delegate for your three UITextField controls to be the object in which you've implemented these various delegate methods.
If you want to control the behavior of the return key, implement the textFieldShouldReturn method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.nameField) {
[self.ageField becomeFirstResponder];
} else if (textField == self.ageField) {
[self.sexField becomeFirstResponder];
} else if (textField == self.sexField) {
[textField resignFirstResponder];
[self saveResults];
}
return NO;
}
I'd generally be inclined to do something like the above, where pressing return takes me to the next field, and pressing return on the last one dismisses the keyboard and tries to save the results.
BTW, in IB, I'd make sure that the "return key" setting for the first two control would be "Next", and for the last one, either "Go" or "Done".
Your save routine would simply populate an object with the contents of the three controls:
- (void)saveResults
{
Person *person = [[Person alloc] init];
person.name = self.nameField.text;
if (self.ageField.text) {
person.age = #([self.ageField.text integerValue]);
}
person.sex = self.sexField.text;
// now do whatever you want with this object
}
This obviously assumes that you have a Person class:
#interface Person : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, strong) NSNumber *age;
#property (nonatomic, copy) NSString *sex;
#end
#implementation Person
#end
If you'd rather use a NSDictionary or NSArray, that's fine, too (make sure you check the text fields are not nil, though), though I personally prefer a well-defined model object like above.
As a refinement, you might want to make sure you only enter numeric values for age (if that's how you want to store the age):
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.ageField) {
NSCharacterSet *invalid = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890"] invertedSet];
NSRange range = [string rangeOfCharacterFromSet:invalid];
return range.location == NSNotFound; // if non-numeric character not found, return true
}
return YES;
}

Particle emitter works in one app, but not another

I've been experiencing some difficulties with particle effects. Originally I posted a question about how the particle effects in my app were different when on an ios6 device.
Particle system looks different on iOS 6 and ios7
I Originally designed the app on an ios7 device and got the particles looking like I wanted, but on the ios6 device the particles were smaller and displaced.
I was told it was problem between ios6 and ios7 and that changing the media timing could fix it.
Ive tried everything, but nothing has worked.
Eventually I tried just creating a separate app and pasted in the code from this tutorial - http://weblog.invasivecode.com/post/45058779586/caemitterlayer-and-the-ios-particle-system-lets in the view did load. The particles work as they should, but when I put the same code into my current apps viewDidLoad. The particles were all over the place and not doing what they should be.
I'm wandering if there is something in my current app that Im missing, that is upsetting the particles. Can anyone suggest things to look for?
Originally the particle effects were subclassed and being called after adding a subview to my main view.
Here is my view controller .h code (I've taken out some irrelevant control object properties and outlets)
#interface HHViewController : UIViewController < HHScoreViewdelegate>
{
IBOutlet UIButton* btnStart;
IBOutlet UIButton* btnStop;
IBOutlet UIButton* btnMore;
IBOutlet UIButton* btnHelp;
IBOutlet UIButton* btnTessilaCoil;
IBOutlet UIImageView* imgAnimatedTessila;
IBOutlet UIImageView* imgBubble;
IBOutlet UIImageView* imgSteam;
IBOutlet UIImageView* imgMachineLightsTop;
IBOutlet UIImageView* imgBackground;
NSTimer* StopSignTimer;
NSTimer* timer;
NSTimer* lightMachineTimer;
NSTimer* ComputerLightsTimer;
CGFloat AnimationDelay;
AVAudioPlayer* audioPlayer;
AVAudioPlayer* audioPlayer2; //Used for game end audio, so that it doesnt interupt last letter/number audio
int pageValue;
IBOutlet UIButton* btnSetting;
IBOutlet UIButton* btnIAP;
IBOutlet UIButton* btnNext;
IBOutlet UIButton* btnForward;
IBOutlet UIImageView* imgLightMachine;
IBOutlet UIImageView* imgComputerLights;
NSString* strletterName;
HHScoreView * scoreSelection;
More * MorePanelView;
InAppPurchase * InAppPurchaseView;
NSMutableArray* ButtonBackgroundImages;
NSMutableArray* AlphabetBubbles;
NSMutableArray* SavedBubblePositions;
NSTimer* bubbleBlinkingTimer;
int wrongbubbleTapCount;
IBOutlet UIImageView* imgAlphabetDisplay;
IBOutlet UILabel* lblNextOneToPop;
// Code from Particle Tutorial
CAEmitterLayer *_myEmitter;
CAEmitterCell *_myCell;
// End code form Particle Tutorial
}
// Code from Particle Tutorial
#property(nonatomic, retain) CAEmitterLayer *_myEmitter;
#property(nonatomic, retain) CAEmitterCell *_myCell;
// End code form Particle Tutorial
#property(nonatomic,strong) UILabel* lblNextOneToPop;
#property(nonatomic,strong) NSTimer* SteamTimer;
#property(nonatomic,strong) NSTimer* StopSignTimer;
#property(nonatomic,strong) NSTimer* timer;
#property(nonatomic,strong) NSTimer* lightMachineTimer;
#property(nonatomic,strong) NSTimer* ComputerLightsTimer;
#property(nonatomic,retain)IBOutlet UIButton* btnStart;
#property(nonatomic,retain)IBOutlet UIButton* btnStop;
#property(nonatomic,retain)IBOutlet UIButton* btnMore;
#property(nonatomic,retain)IBOutlet UIButton* btnHelp;
#property(nonatomic,retain)IBOutlet UIButton* btnSetting;
#property(nonatomic,retain)IBOutlet UIButton* btnTessilaCoil;
#property(nonatomic,retain)IBOutlet UIImageView* imgAnimatedTessila;
#property(nonatomic,retain)IBOutlet UIImageView* imgSteam;
#property(nonatomic,retain)IBOutlet UIImageView* imgMachineLightsTop;
#property(nonatomic,retain)IBOutlet UIImageView* imgBackground;
#property(nonatomic,retain)IBOutlet UIScrollView* scScrollView;
#property(nonatomic,retain)IBOutlet IBOutlet UIButton* btnNext;
#property(nonatomic,retain)IBOutlet IBOutlet UIButton* btnForward;
#property(nonatomic,retain)IBOutlet UIImageView* imgLightMachine;
#property(nonatomic,retain)IBOutlet UIImageView* imgComputerLights;
#property(nonatomic,retain)NSString* strletterName;
#property(assign)int allLettersEventCount;
#property(nonatomic,retain) NSArray* ButtonBackgroundImages;
#property Boolean StopButtonClicked;
#property Boolean BubbleAOnscreen;
#property (nonatomic,assign) BOOL cancelAll;
#property int pageValue;
#property int positionRotation;
-(IBAction)tapPiece:(UITapGestureRecognizer *)recognizer;
-(IBAction)actionStartSign:(id)sender;
-(IBAction)actionStopSign:(id)sender;
-(IBAction)actionMoreSign:(id)sender;
-(IBAction)actionHelpSign:(id)sender;
-(IBAction)actionTessilaCoil:(id)sender;
-(IBAction)actionbtnHelp:(id)sender;
-(IBAction)actionbtnSetting:(id)sender;
-(IBAction)actionbtnIAP:(id)sender;
+(HHViewController*)sharedManager;
- (IBAction)purchaseItem:(id)sender;
#property (strong, nonatomic) InAppPurchase *purchaseController;
#end
Here is the code from my viewcontroller .m where I added the code from the tutorial.
#interface HHViewController ()
{
}
#end
#implementation HHViewController
static int OrderingSequence = 0;
#synthesize _myEmitter, _myCell;
/*
TeslarGlowEffect* ShowGlow;
SteamEffect* ShowSteam;
BubbleBurst* PopBubble;
*/
//TeslarTimerSparks* TeslarTimer;
- (void)viewDidLoad
{
[super viewDidLoad];
CFTimeInterval currentTime = [self.view.layer convertTime:CACurrentMediaTime() fromLayer:nil];
NSLog(#"Current media Timing = %f", currentTime);
// Code from tutorial
CAEmitterLayer *emitterLayer = [CAEmitterLayer layer]; // 1
emitterLayer.emitterPosition = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.origin.y); // 2
emitterLayer.emitterZPosition = 10; // 3
emitterLayer.emitterSize = CGSizeMake(self.view.bounds.size.width, 0); // 4
emitterLayer.emitterShape = kCAEmitterLayerSphere; // 5
CAEmitterCell *emitterCell = [CAEmitterCell emitterCell]; // 6
emitterCell.scale = 0.1; // 7
emitterCell.scaleRange = 0.2; // 8
emitterCell.emissionRange = (CGFloat)M_PI_2; // 9
emitterCell.lifetime = 5.0; // 10
emitterCell.birthRate = 10; // 11
emitterCell.velocity = 200; // 12
emitterCell.velocityRange = 50; // 13
emitterCell.yAcceleration = 250; // 14
emitterCell.contents = (id)[[UIImage imageNamed:#"Steam1.png"] CGImage]; // 15
emitterLayer.emitterCells = [NSArray arrayWithObject:emitterCell]; // 16
[self.view.layer addSublayer:emitterLayer]; // 17
//end code from tutorial
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillEnterForegroundNotification:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillEnterBackgroundNotification:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[btnStart addTarget:self action:#selector(actionStartSign:) forControlEvents:UIControlEventTouchUpInside];
//NSLog(#"OrderingSequence = %d",OrderingSequence );
imgAnimatedTessila.image = [UIImage imageNamed:KTESSILAIMAGE];
self.alphebetindex = 0;
wrongbubbleTapCount = 0;
//// Load a bunch of arrays used in the game.
[btnHelp addTarget:self action:#selector(actionbtnHelp:) forControlEvents:UIControlEventTouchUpInside];
[btnSetting addTarget:self action:#selector(actionbtnSetting:) forControlEvents:UIControlEventTouchUpInside];
NSString* strFirstTimeloaded = [[NSUserDefaults standardUserDefaults]valueForKey:#"FirstTime"];
if(strFirstTimeloaded == nil)
{
// Show preference page if first time used.
[[NSUserDefaults standardUserDefaults]setValue:#"English" forKey:#"Language"];
LanguagesSelectView* selection = [[LanguagesSelectView alloc]initWithFrame:CGRectMake(0, 0, 1024, 748)];
[self.view addSubview:selection];
[[NSUserDefaults standardUserDefaults]setValue:#"FirstTime" forKey:#"FirstTime"];
}
positionRotation = 0;
self.strletterName = #"29";
self.allLettersEventCount = 0;
[[NSUserDefaults standardUserDefaults] setValue:#"One" forKey:#"Mode"];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(enableSetting) name:#"EnableSetting" object:nil];
//[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(LetterTapped:) name:#"LetterTapped" object:nil];
btnStop.hidden = YES;
btnNext.hidden = YES;
btnForward.hidden = YES;
[self addGestureRecognizersToView];
//Create timer for release of steam from bubble machine
SteamTimer = [NSTimer scheduledTimerWithTimeInterval:5.2 target:self selector:#selector(ShowSteamEffect) userInfo:nil repeats:YES];
//Set Font for lblNextOneToPop
[lblNextOneToPop setFont:[UIFont fontWithName:#"SF Slapstick Comic" size:110]];
lblNextOneToPop.hidden = YES;
}
Here is one of my particle effects that was working on my ios7 iPad, but on the ios6 iPad, the effect looked totally different.
It was after long hrs trying to figure out why the ios7 and ios6 looked different that I tried the exercise of putting the tutorial code into a new app and then it into my own app. In my app the particles are totally different, but as they should be in the new app.
With respect to #matt's comments below. I know there must be something going on with my app, but I can't see it. I've looked all over the web and all through my code and I think I'm missing something.
All I want are three particles effects that appear at specific locations regardless of iOS version. One of them on user touch. The effect below is just one of them. I've tried the CAmediaTiming thing, but that didn't work.
SteamEffect.h
#import <UIKit/UIKit.h>
#interface SteamEffect : UIView
#end
The steamEffect.m looks like this.
#import "SteamEffect.h"
#implementation SteamEffect
{
CAEmitterLayer* SteamEmitter;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
SteamEmitter = (CAEmitterLayer*) self.layer;
//SteamEmitter.emitterPosition= CGPointMake(0, 0);
//SteamEmitter.emitterSize = CGSizeMake(10,10);
CAEmitterCell* Steam = [CAEmitterCell emitterCell];
Steam.birthRate = 50.0f;
Steam.spin = .6f;
Steam.lifetime = 1.7f;
Steam.alphaRange = 0.2f;
Steam.alphaSpeed = 0.2f;
Steam.contents = (id)[[UIImage imageNamed:#"Steam1.png"]CGImage];
Steam.velocity = 30;
Steam.velocityRange = 50.0f;
Steam.emissionLongitude = -60.0f;
Steam.emissionRange = M_1_PI;
Steam.scale = .2f;
Steam.scaleSpeed = .5f;
Steam.yAcceleration = -200.0f;
//SteamEmitter.renderMode = kCAEmitterLayerBackToFront;//kCAEmitterLayerAdditive;
//SteamEmitter.emitterShape = kCAEmitterLayerCircle;
SteamEmitter.emitterCells = #[Steam];
SteamEmitter.emitterPosition = CGPointMake(815, 445);
//Check System Version
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ([[vComp objectAtIndex:0] intValue] == 7) {
// iOS-6 code
SteamEmitter.beginTime = CACurrentMediaTime();
}
}
return self;
}
-(void)didMoveToSuperview
{
//1
[super didMoveToSuperview];
if (self.superview==nil) return;
[self performSelector:#selector(disableEmitterCell) withObject:nil afterDelay:0.5];
}
-(void)disableEmitterCell
{
[SteamEmitter setValue:#0 forKeyPath:#"birthRate"];
}
+ (Class) layerClass
{
//tell UIView to use the CAEmitterLayer root class
return [CAEmitterLayer class];
}
- (void) setEmitterPosition:(CGPoint)pos
{
SteamEmitter.emitterPosition = pos;
}
- (void) toggleOn:(bool)on
{
//SteamEmitter.birthRate = on? 300 : 0;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
I called the above from my viewcontroller .m using the following. There is also a timer in the viewDidLoad above that calls this every 5 sec. Although that is probably not the way to do it. Probably better to add the view and start it emitting every 5 sec rather than adding a new view each time, but thats a different issue.
- (void)ShowSteamEffect
{
//Check System Version because NSAttributedString only works in ios6 and above.
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
//Create view for Steam particle effect.
//CGRect SteamFrame = CGRectMake(790, 380, 100, 100); //ORIGINAL
CGRect SteamFrame = CGRectMake(0, 0, 0, 0); //(815, 455, 100, 100)
//Show Steam effect
ShowSteam = [[SteamEffect alloc]initWithFrame:SteamFrame];
ShowSteam.hidden = NO;
[self.view insertSubview:ShowSteam aboveSubview:imgComputerLights];
}

UnEven Behaviour of UIView when setHidden

I've created 5 UIView dynamically, which consists of one UILabel and one UIButton each. When I click button, the UIView will setHidden. But it works only on one not other four uiviews.
#interface ViewController : UIViewController
{
NSMutableArray *newViews;
}
#property(nonatomic,retain)IBOutlet UILabel *welcome;
#property(nonatomic,retain)CustomView *custom;
-(void)buttonPressed:(UIButton *)sender;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *name=#"string of length";
int length=[name length];
newViews = [NSMutableArray array];
NSMutableArray *myArray = [NSMutableArray arrayWithObjects:#"cricket", #"golf",#"wrestling", #"FootBall is good game", nil];
int yAxis=44;
int lengthOfArray=[myArray count];
for(int a=0; a<=lengthOfArray; a++){
self.custom= [[CustomView alloc]initWithFrame:CGRectMake(20, yAxis, 100, 44)];
yAxis=yAxis+50;
NSLog(#"yaxis is %i",yAxis);
self.custom.tag=200+a;
[newViews addObject:self.custom];
self.custom.Label = [[UILabel alloc]initWithFrame:CGRectMake(5,5, length+70, 30)];
self.custom.button=[[UIButton alloc]initWithFrame:CGRectMake(85,10,12,10)];
UIImage *btnImage = [UIImage imageNamed:#"button_droparrow.png"];
[self.custom.button setImage:btnImage forState:UIControlStateNormal];
[self.custom.button addTarget:self action:#selector(buttonPressed:)forControlEvents:UIControlEventTouchDown];
self.custom.button.tag=self.custom.button.tag+a;
self.custom.backgroundColor=[UIColor greenColor];
custom.Label.text=#"welcome";
custom.Label.backgroundColor = [UIColor yellowColor];
[self.custom addSubview:self.custom.button];
[self.custom addSubview:custom.Label];
[self.view addSubview:self.custom];
}
[self.custom.button addTarget:self action:#selector(buttonPressed:)forControlEvents:UIControlEventTouchDown];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)buttonPressed:(UIButton *)sender
{
[self.custom setHidden:YES];
}
#end
Kindly help me. I am new in iOS development. I need here to create UIView with differrnt reference and that reference assign to UIButton to close that particular UIView but I could not get result out.
You could use UISegmentedControl along with number of xib for each UIView.
In each UIView you can place the required UIControls and link the same.
In the delegate method of SegmentedControl 'indexDidChangeForSegmentedControl:(UISegmentedControl *)sender' on each index remove the earlier UIView and add the required UIView.
In the main header file add the IBOutlet for each UIView
#property (nonatomic, weak) IBOutlet UIView *view1;
#property (nonatomic, weak) IBOutlet UIView *view2;
In .m file in the delegate method 'indexDidChangeForSegmentedControl'
- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl *)sender {
NSUInteger index = sender.selectedSegmentIndex;
if (UISegmentedControlNoSegment != index) {
if (currentIndex == index) {
return;
}
currentIndex = index;
switch (index) {
case 0:
{
[self.previousView removeFromSuperview];
[self.view addSubview:view1];
self.previousView = view1;
}
break;
case 1:
{
[self.previousView removeFromSuperview];
[self.view addSubview:view2];
self.previousView = view2;
}
break;
}
}
}
Hope this helps.
If you want to use properties, you will have to make a property for each view. Instead, if you want to create them dynamicaly you could store the references to each view in an array.
The next you should know/do is to add a tag to each button. A tag is just a number, which in this case should reference to its position in the Array.
Then based on the button tag (that you can retrieve from the sender) you can retrieve the proper view/button from the array and change the Hidden property on it.
For example (pseudo code/this wont compile):
Creating the views array
#property (nonatomic, strong) NSMutableArray *views;
In View did load create the views
views = [[NSMutableArray alloc] init];
int nrOfViews = 5;
for(int a=0; a<=nrOfViews; a++){
UIView *view = create UIView here.
UIButton *button = create button here.
[view addSubView: button];
[button setTag: a];
[views addObject: view];
}
reference to the view through the pointer retained in the array, find the right one based on the button tag.
-(void)buttonPressed:(UIButton *)sender
{
UIView *view = [views objectAtIndex: sender.tag]; //using the button tag to identify the right view.
[view setHidden: yes];
}
Try something like this:
- (void) buttonPressed: (UIButton*) sender
{
UIView* view = sender.superview;
view.hidden = YES;
}
You need to make some changes as follows
#property(nonatomic,strong)IBOutlet UILabel *welcome; // new arc code
#property(nonatomic,strong)UIView *custom; // new arc code
self.custom = [[UIView alloc]initWithFrame:CGRectMake(20, yAxis, 100, 44)];

Resources