I'm trying to display the yaw pitch and roll of the device in a label. I cannot seem to get the values to display, it only shows a '...' where the numbers should be. This is my code, any help is greatly appreciated.
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
#interface ViewController (){
}
#property (strong, nonatomic) CMMotionManager *motionManager;
#end
#implementation ViewController
#synthesize motionManager;
#synthesize roll;
#synthesize pitch;
#synthesize yaw;
#synthesize xLabel;
#synthesize yLabel;
#synthesize zLabel;
- (void)viewDidLoad {
[super viewDidLoad];
/** Do any additional setup after loading the view, typically from a nib.
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.updateInterval = 1.0f/60.0f;
accelerometer.delegate = self;
**/
//motionManager = [[CMMotionManager alloc] init];
//motionManager.deviceMotionUpdateInterval = 1.0 / 60.0;
motionManager = [[CMMotionManager alloc] init];
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:#selector(doGyroUpdate) userInfo:nil repeats:YES];
//CMDeviceMotion *deviceMotion = motionManager.deviceMotion;
//CMAttitude *attitude = deviceMotion.attitude;
[motionManager startDeviceMotionUpdates];
}
-(void)doGyroUpdate
{
double x = motionManager.deviceMotion.attitude.roll*180/M_PI;
double y = motionManager.deviceMotion.attitude.pitch*180/M_PI;
double z = motionManager.deviceMotion.attitude.yaw*180/M_PI;
NSString *myString = [NSString stringWithFormat:#"%g", x];
xLabel.text = myString;
myString = [NSString stringWithFormat:#"%f", y];
yLabel.text = myString;
myString = [NSString stringWithFormat:#"%f", z];
zLabel.text = myString;
}
... indicates the UILabel you're using for displaying the text is not as wide as it should be.
Try and make it wider in your storyboard or xib file.
Try -
label.numberOfLines = 1;
label.minimumFontSize = 6;
label.adjustsFontSizeToFitWidth = YES;
Or you can try it by storyboard (Autoshrink option) -
You can use Autolayout for this. Here I have given 2 constraint
1. top from superView
2. leading from superview
Now whatever is your text it will display without .... .
Related
I'm trying programmatically implement this layout:
[label|label|slider|label|textField]
[label|label|slider|label|textField]
[label|label|slider|label|textField]
this is vertical layout with horizontal layouts inside
First problem, what will be the slider size? Unknown, so I add width constraint:
[stackView addConstraint:[NSLayoutConstraint constraintWithItem:slider
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:150]];
but i'm not sure if it's ok to add constrain in stackView, correct me please if I'm wrong.
Vertical stackView have Leading alignment, Horizontal - Center alignment, here is build result
I want to align everything left, but I don't know how, I can do this using IB but the same settings programmatically not working :(
P.S. Also sometimes I'm getting this in log:
Failed to rebuild layout engine without detectable loss of precision. This should never happen. Performance and correctness may suffer.
UIStackView is great, except when it's not.
To use the approach you're taking - a Vertical UIStackView with "rows" of Horizontal stack views - you'll need to explicitly set a width constraint on every element.
Without explicit widths, you get:
|Description Label|Val-1|--slider--|Val-2|Input|
|Short label|123|--slider--|123|42.6623|
|A much longer label|0|--slider--|0|-42.6623|
As you can see, the first element in each row - the Description Label - does not have an equal width to the other row's Description Labels, and the separate stack views will arrange them based on their intrisic widths. In this case, the length of the text.
So, you either need to decide ahead of time that Description Label has a width of, say, 80; Val-1 has a width of 40; Slider has a width of 150; Val-2 has a width of 80; and Input has a width of 100.
Now you'll be able to get:
|Description Label |Val-1|--slider--|Val-2| Input |
|Short label | 123 |--slider--| 123 | 42.6623 |
|A much longer label | 0 |--slider--| 0 | -42.6623 |
I don't think you want a width constraint on the slider. Looking at your screen shot, I guess you probably want this:
So we have some parameters. Each parameter has a name, a minimum value, a maximum value, and a current value. For each parameter, we have one row showing all of the parameter's properties, with the current value shown as both a slider and a text field. The name labels all have the same width, which is the narrowest width that doesn't clip any of the labels. Same for the minimum and maximum value labels. The value text fields all have the same width, and it is the narrowest width that won't clip the value string even at the minimum or maximum value. The slider expands or contracts as needed to fill all remaining space in its row.
Here's how I did it, all in code.
First, I made a Parameter class:
#interface Parameter: NSObject
#property (nonatomic, copy, readonly, nonnull) NSString *name;
#property (nonatomic, readonly) double minValue;
#property (nonatomic, readonly) double maxValue;
#property (nonatomic) double value;
- (instancetype _Nonnull)initWithName:(NSString *_Nonnull)name minValue:(double)minValue maxValue:(double)maxValue initialValue:(double)value;
#end
#implementation Parameter
- (instancetype)initWithName:(NSString *)name minValue:(double)minValue maxValue:(double)maxValue initialValue:(double)value {
if (self = [super init]) {
_name = [name copy];
_minValue = minValue;
_maxValue = maxValue;
_value = value;
}
return self;
}
#end
Then I made a ParameterView class with this interface:
#interface ParameterView: UIStackView
#property (nonatomic, strong, readonly, nonnull) Parameter *parameter;
#property (nonatomic, strong, readonly, nonnull) UILabel *nameLabel;
#property (nonatomic, strong, readonly, nonnull) UILabel *minValueLabel;
#property (nonatomic, strong, readonly, nonnull) UISlider *valueSlider;
#property (nonatomic, strong, readonly, nonnull) UILabel *maxValueLabel;
#property (nonatomic, strong, readonly, nonnull) UITextField *valueTextField;
- (instancetype _Nonnull)initWithParameter:(Parameter *_Nonnull)parameter;
#end
Notice that ParameterView is a subclass of UIStackView. The initializer looks like this:
static void *kvoParameterValue = &kvoParameterValue;
#implementation ParameterView
- (instancetype)initWithParameter:(Parameter *)parameter {
if (self = [super init]) {
self.axis = UILayoutConstraintAxisHorizontal;
self.alignment = UIStackViewAlignmentFirstBaseline;
self.spacing = 2;
_parameter = parameter;
_nameLabel = [self pv_labelWithText:[parameter.name stringByAppendingString:#":"] alignment:NSTextAlignmentRight];
_minValueLabel = [self pv_labelWithText:[NSString stringWithFormat:#"%.0f", parameter.minValue] alignment:NSTextAlignmentRight];
_maxValueLabel = [self pv_labelWithText:[NSString stringWithFormat:#"%.0f", parameter.maxValue] alignment:NSTextAlignmentLeft];
_valueSlider = [[UISlider alloc] init];
_valueSlider.translatesAutoresizingMaskIntoConstraints = NO;
_valueSlider.minimumValue = parameter.minValue;
_valueSlider.maximumValue = parameter.maxValue;
_valueTextField = [[UITextField alloc] init];
_valueTextField.translatesAutoresizingMaskIntoConstraints = NO;
_valueTextField.borderStyle = UITextBorderStyleRoundedRect;
_valueTextField.text = [self stringWithValue:parameter.minValue];
CGFloat width = [_valueTextField systemLayoutSizeFittingSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width;
_valueTextField.text = [self stringWithValue:parameter.maxValue];
width = MAX(width, [_valueTextField systemLayoutSizeFittingSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width);
[_valueTextField.widthAnchor constraintGreaterThanOrEqualToConstant:width].active = YES;
[self addArrangedSubview:_nameLabel];
[self addArrangedSubview:_minValueLabel];
[self addArrangedSubview:_valueSlider];
[self addArrangedSubview:_maxValueLabel];
[self addArrangedSubview:_valueTextField];
[_parameter addObserver:self forKeyPath:#"value" options:0 context:kvoParameterValue];
[_valueSlider addTarget:self action:#selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
[self updateViews];
}
return self;
}
Notice that I set a greater-than-or-equal-to constraint on _valueTextField.widthAnchor, after finding the minimum width that can show both the minimum and maximum values without clipping.
I use a helper method to create each of the label values, since they are all created the same way:
- (UILabel *)pv_labelWithText:(NSString *)text alignment:(NSTextAlignment)alignment {
UILabel *label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.text = text;
label.textAlignment = alignment;
[label setContentCompressionResistancePriority:UILayoutPriorityRequired - 1 forAxis:UILayoutConstraintAxisHorizontal];
[label setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
return label;
}
What I'm doing here is setting the horizontal content compression resistance priority very high, so that none of the labels will clip its content. But then I'm setting the horizontal hugging priority fairly high (but not as high) so that each label will try to be as narrow as possible (without clipping).
To make the columns of labels line up, I need one more method:
- (void)constrainColumnsToReferenceView:(ParameterView *)referenceView {
[NSLayoutConstraint activateConstraints:#[
[_nameLabel.widthAnchor constraintEqualToAnchor:referenceView.nameLabel.widthAnchor],
[_minValueLabel.widthAnchor constraintEqualToAnchor:referenceView.minValueLabel.widthAnchor],
[_valueSlider.widthAnchor constraintEqualToAnchor:referenceView.valueSlider.widthAnchor],
[_maxValueLabel.widthAnchor constraintEqualToAnchor:referenceView.maxValueLabel.widthAnchor],
[_valueTextField.widthAnchor constraintEqualToAnchor:referenceView.valueTextField.widthAnchor],
]];
}
Since this creates constraints between the views in two different rows, I can't use it until both rows have a common superview. So I use it in my view controller's 'viewDidLoad`:
- (void)viewDidLoad {
[super viewDidLoad];
UIStackView *rootStack = [[UIStackView alloc] init];
rootStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:rootStack];
[NSLayoutConstraint activateConstraints:#[
[rootStack.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:8],
[rootStack.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:8],
[rootStack.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-8],
]];
rootStack.axis = UILayoutConstraintAxisVertical;
rootStack.spacing = 2;
rootStack.alignment = UIStackViewAlignmentFill;
ParameterView *firstParameterView;
for (Parameter *p in _parameters) {
ParameterView *pv = [[ParameterView alloc] initWithParameter:p];
[rootStack addArrangedSubview:pv];
if (firstParameterView == nil) {
firstParameterView = pv;
} else {
[pv constrainColumnsToReferenceView:firstParameterView];
}
}
}
And here is my complete ViewController.m file, in case you want to play with it. Just copy and paste it into a newly-created iOS project.
#import "ViewController.h"
#interface Parameter: NSObject
#property (nonatomic, copy, readonly, nonnull) NSString *name;
#property (nonatomic, readonly) double minValue;
#property (nonatomic, readonly) double maxValue;
#property (nonatomic) double value;
- (instancetype _Nonnull)initWithName:(NSString *_Nonnull)name minValue:(double)minValue maxValue:(double)maxValue initialValue:(double)value;
#end
#implementation Parameter
- (instancetype)initWithName:(NSString *)name minValue:(double)minValue maxValue:(double)maxValue initialValue:(double)value {
if (self = [super init]) {
_name = [name copy];
_minValue = minValue;
_maxValue = maxValue;
_value = value;
}
return self;
}
#end
#interface ParameterView: UIStackView
#property (nonatomic, strong, readonly, nonnull) Parameter *parameter;
#property (nonatomic, strong, readonly, nonnull) UILabel *nameLabel;
#property (nonatomic, strong, readonly, nonnull) UILabel *minValueLabel;
#property (nonatomic, strong, readonly, nonnull) UISlider *valueSlider;
#property (nonatomic, strong, readonly, nonnull) UILabel *maxValueLabel;
#property (nonatomic, strong, readonly, nonnull) UITextField *valueTextField;
- (instancetype _Nonnull)initWithParameter:(Parameter *_Nonnull)parameter;
#end
static void *kvoParameterValue = &kvoParameterValue;
#implementation ParameterView
- (instancetype)initWithParameter:(Parameter *)parameter {
if (self = [super init]) {
self.axis = UILayoutConstraintAxisHorizontal;
self.alignment = UIStackViewAlignmentCenter;
self.spacing = 2;
_parameter = parameter;
_nameLabel = [self pv_labelWithText:[parameter.name stringByAppendingString:#":"] alignment:NSTextAlignmentRight];
_minValueLabel = [self pv_labelWithText:[NSString stringWithFormat:#"%.0f", parameter.minValue] alignment:NSTextAlignmentRight];
_maxValueLabel = [self pv_labelWithText:[NSString stringWithFormat:#"%.0f", parameter.maxValue] alignment:NSTextAlignmentLeft];
_valueSlider = [[UISlider alloc] init];
_valueSlider.translatesAutoresizingMaskIntoConstraints = NO;
_valueSlider.minimumValue = parameter.minValue;
_valueSlider.maximumValue = parameter.maxValue;
_valueTextField = [[UITextField alloc] init];
_valueTextField.translatesAutoresizingMaskIntoConstraints = NO;
_valueTextField.borderStyle = UITextBorderStyleRoundedRect;
_valueTextField.text = [self stringWithValue:parameter.minValue];
CGFloat width = [_valueTextField systemLayoutSizeFittingSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width;
_valueTextField.text = [self stringWithValue:parameter.maxValue];
width = MAX(width, [_valueTextField systemLayoutSizeFittingSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width);
[_valueTextField.widthAnchor constraintGreaterThanOrEqualToConstant:width].active = YES;
[self addArrangedSubview:_nameLabel];
[self addArrangedSubview:_minValueLabel];
[self addArrangedSubview:_valueSlider];
[self addArrangedSubview:_maxValueLabel];
[self addArrangedSubview:_valueTextField];
[_parameter addObserver:self forKeyPath:#"value" options:0 context:kvoParameterValue];
[_valueSlider addTarget:self action:#selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
[self updateViews];
}
return self;
}
- (UILabel *)pv_labelWithText:(NSString *)text alignment:(NSTextAlignment)alignment {
UILabel *label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.text = text;
label.textAlignment = alignment;
[label setContentCompressionResistancePriority:UILayoutPriorityRequired - 1 forAxis:UILayoutConstraintAxisHorizontal];
[label setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
return label;
}
- (void)constrainColumnsToReferenceView:(ParameterView *)referenceView {
[NSLayoutConstraint activateConstraints:#[
[_nameLabel.widthAnchor constraintEqualToAnchor:referenceView.nameLabel.widthAnchor],
[_minValueLabel.widthAnchor constraintEqualToAnchor:referenceView.minValueLabel.widthAnchor],
[_valueSlider.widthAnchor constraintEqualToAnchor:referenceView.valueSlider.widthAnchor],
[_maxValueLabel.widthAnchor constraintEqualToAnchor:referenceView.maxValueLabel.widthAnchor],
[_valueTextField.widthAnchor constraintEqualToAnchor:referenceView.valueTextField.widthAnchor],
]];
}
- (void)sliderValueChanged:(UISlider *)slider {
_parameter.value = slider.value;
}
- (void)updateViews {
_valueSlider.value = _parameter.value;
_valueTextField.text = [self stringWithValue:_parameter.value];
}
- (NSString *)stringWithValue:(double)value {
return [NSString stringWithFormat:#"%.4f", value];
}
- (void)dealloc {
[_parameter removeObserver:self forKeyPath:#"value" context:kvoParameterValue];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if (context == kvoParameterValue) {
[self updateViews];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#end
#interface ViewController ()
#end
#implementation ViewController {
NSArray<Parameter *> *_parameters;
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder:decoder]) {
_parameters = #[
[[Parameter alloc] initWithName:#"Rotation, deg" minValue:-180 maxValue:180 initialValue:61.9481],
[[Parameter alloc] initWithName:#"Field of view scale" minValue:0 maxValue:1 initialValue:0.7013],
[[Parameter alloc] initWithName:#"Fisheye lens distortion" minValue:0 maxValue:1 initialValue:0.3041],
[[Parameter alloc] initWithName:#"Tilt vertical" minValue:-90 maxValue:90 initialValue:42.6623],
[[Parameter alloc] initWithName:#"X" minValue:-1 maxValue:1 initialValue:0.6528],
[[Parameter alloc] initWithName:#"Y" minValue:-1 maxValue:1 initialValue:-0.3026],
[[Parameter alloc] initWithName:#"Z" minValue:-1 maxValue:1 initialValue:0],
];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIStackView *rootStack = [[UIStackView alloc] init];
rootStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:rootStack];
[NSLayoutConstraint activateConstraints:#[
[rootStack.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:8],
[rootStack.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:8],
[rootStack.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-8],
]];
rootStack.axis = UILayoutConstraintAxisVertical;
rootStack.spacing = 4;
rootStack.alignment = UIStackViewAlignmentFill;
ParameterView *firstParameterView;
for (Parameter *p in _parameters) {
ParameterView *pv = [[ParameterView alloc] initWithParameter:p];
[rootStack addArrangedSubview:pv];
if (firstParameterView == nil) {
firstParameterView = pv;
} else {
[pv constrainColumnsToReferenceView:firstParameterView];
}
}
}
#end
Goal is to enumerate every character in the String. That is 'w' will appear then after 1 sec will be replaced by 'h' then 'e' then 'n'.
Problem my label only shows the last letter.
What i did:
1. drag a label and a button on the PlayViewController.
2. create the property for Label
3. create action for button
In my PlayViewController.h:
#import <UIKit/UIKit.h>
#interface PlayViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *listChar;
- (IBAction)startGame:(id)sender;
#end
In my PlayViewController.m:
#import "PlayViewController.h"
#interface PlayViewController ()
#end
#implementation PlayViewController
NSString *word;
NSTimer *myTimer;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.listChar.text = #" ";
word = #"when";
}
- (IBAction)startGame:(id)sender {
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(listLetter:) userInfo:nil repeats:YES];
}
-(void) listLetter:(NSTimer*) myTimer {
for(int i=0; i<[word length]; i++){
unichar letter = [word characterAtIndex: i];
self.listChar.text = [NSString stringWithFormat:#"%C", letter];
}
}
#end
If you want to know about why this happning then refer #Nitin's answer, and if you want to solve in other way then just use following code
-(void) listLetter:(NSTimer*) myTimer
static int pos = 1;
self.listChar.text = [word substringToIndex:pos];
if (++pos > word.length) {
[myTimer invalidate];
}
}
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];
}
I want to display remaining time from my NSTimer in NavigationItem title, that's why I can't create outlet for it.
My code is from this question NSTimer problem:
#interface MyController : UIViewController
{
UILabel * theLabel;
#private
NSTimer * countdownTimer;
NSUInteger remainingTicks;
}
#property (nonatomic, retain) IBOutlet UILabel * theLabel;
-(IBAction)doCountdown: (id)sender;
-(void)handleTimerTick;
-(void)updateLabel;
#end
#implementation MyController
#synthesize theLabel;
-(IBAction)doCountdown: (id)sender
{
if (countdownTimer)
return;
remainingTicks = 60;
[self updateLabel];
countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: #selector(handleTimerTick) userInfo: nil repeats: YES];
}
-(void)handleTimerTick
{
remainingTicks--;
[self updateLabel];
if (remainingTicks <= 0) {
[countdownTimer invalidate];
countdownTimer = nil;
}
}
-(void)updateLabel
{
theLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue];
}
#end
So, how can I put theLabel.text to label in NavigationBar?
I call method doCountdown in viewDidLoad:
[self doCountdown:nil];
Where is my fault? If I try to watch theLabel, NSLog says (null).
UPD:
And another stupid question. If I try to move label with NSTimer to the right, like here:
[self.navigationItem setTitle:#"Экзамен"];
self.theLabel = [[UILabel alloc] init];
[self doCountdown:nil];
UILabel *yourLabel = [[UILabel alloc]initWithFrame:CGRectMake(260,6,55,32)];
yourLabel.text = self.theLabel.text;
[self.navigationController.navigationBar addSubview:yourLabel];
my timer doesn't start, it shows initial time at label and nothing more.
The label is null because you don't create it anywhere.
In your viewDidLoad you should create it and add to navigation item's title view, e.g. like this:
self.theLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)] autorelease];
self.navigationItem.titleView = self.theLabel;
Don't forget to release theLabel in dealloc.
I'm currently working on a Graphs based iOS app. For this I'm using a third party control called F3PlotStrip.
And implementation is something like:
- (void)viewDidLoad
{
_ecgView = [[F3PlotStrip alloc] initWithFrame:CGRectMake(50, 50, 648, 299)];
_ecgView.lineColor = [UIColor greenColor];
_ecgView.lowerLimit = -10.0f;
_ecgView.upperLimit = 10.0f;
[self.view addSubview:_ecgView];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(testGraph:) userInfo:nil repeats:YES];
}
- (void)testGraph:(NSTimer *)a_timer
{
_ecgView.value = 1.0;
}
But I got the result like:
Then I added a UIView in my xib and changed its class to F3PlotStrip then connected it to the outlet as _ecgView.
Then I changed the code like:
- (void)viewDidLoad
{
_ecgView.lineColor = [UIColor greenColor];
_ecgView.lowerLimit = -10.0f;
_ecgView.upperLimit = 10.0f;
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(testGraph:) userInfo:nil repeats:YES];
}
- (void)testGraph:(NSTimer *)a_timer
{
_ecgView.value = 1.0;
}
This time, I got the actual output:
But why the issue is happening when I add the view through code? I can't depend on the second approach (Through IB) because I need to add graphs dynamically. Is there anyway to fix this issue? Or is this a bug of F3PlotStrip?
I started using this widget this morning. I'm in bed on my iPhone now so cannot post what I want to post, but I will when I get into work in the morning.
I've managed to use it and do what you're trying to do with a dynamically added UIView, or should I say, F3PlotStrip.
I've also made the .h and the .m, ARC compliant too. Not sure if you'd done that.
I'll finish up tomorrow with some nice code that uses an NSTimer to read the contents of a NSArray to plot dynamically, with animation. Again with a View I've added to my viewcontroller as a subview.
Not looked in detail at your code as post what I've managed to get working, tomorrow.
Ok - here I am at work, sat in front of Xcode. Here's my VC that I've used as a basic testbed for this widget. I knocked it up quickly last night, but does the job. Initially, I'd added a UIView to my Storyboard first VC and subclassed it to F3PlotStrip. But, given I saw you you were having issues with dynamically adding the UIView, I thought I'd give it a go. The only difference between you're and mine is that I'm setting the UIView's frame after the alloc-init. See what you think. It uses a Sparkline approach as well as animating the graph on to the screen.
//
// PlotViewController.m
// PlotTest
//
// Created by Carl Hine on 16/05/2013.
// Copyright (c) 2013 Carl Hine. All rights reserved.
//
#define COLOUR_POWDER_BLUE [[UIColor alloc] initWithRed:176/255.0f green:224/255.0f blue:230/255.0f alpha:1]
#import "F3PlotStrip.h"
#import "PlotViewController.h"
#interface PlotViewController ()
#property (strong, nonatomic) IBOutlet F3PlotStrip *IBOPLotView;
#property (strong, nonatomic) NSTimer *plotStipTimer;
#property (strong, nonatomic) NSArray *plotData;
#property (nonatomic) NSInteger plotDataArrayIdx;
#property (strong, nonatomic) F3PlotStrip *plotView2;
#end
#implementation PlotViewController
#synthesize plotStipTimer;
#synthesize plotData;
#synthesize plotDataArrayIdx;
BOOL bUsingDynPlot = YES;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)testGraph:(NSTimer *)a_timer {
float RSEFigure = [[self.plotData objectAtIndex:plotDataArrayIdx] floatValue];
if (bUsingDynPlot)
_plotView2.value = RSEFigure;
else
_IBOPLotView.value = RSEFigure;
++plotDataArrayIdx;
if (plotDataArrayIdx == [self.plotData count]) {
[plotStipTimer invalidate];
plotStipTimer = nil;
}
}
- (void)configurePLotStrip:(F3PlotStrip *)plotStrip {
plotDataArrayIdx = 0;
// Random rubbish that makes it look like a heartbeat :
self.plotData = [NSArray arrayWithObjects:[NSNumber numberWithFloat:68.1f],
[NSNumber numberWithFloat:70.2f],
[NSNumber numberWithFloat:71.3f],
[NSNumber numberWithFloat:72.4f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:100.5f],
[NSNumber numberWithFloat:124.5f],
[NSNumber numberWithFloat:10.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:70.6f],
[NSNumber numberWithFloat:70.2f],
[NSNumber numberWithFloat:71.3f],
[NSNumber numberWithFloat:72.4f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:100.5f],
[NSNumber numberWithFloat:124.5f],
[NSNumber numberWithFloat:10.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:70.6f],
[NSNumber numberWithFloat:70.2f],
[NSNumber numberWithFloat:71.3f],
[NSNumber numberWithFloat:72.4f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:100.5f],
[NSNumber numberWithFloat:124.5f],
[NSNumber numberWithFloat:10.5f],
[NSNumber numberWithFloat:73.5f],
[NSNumber numberWithFloat:70.6f],
nil];
// Get value bounds
float max = -999999;
float min = 999999;
for (NSInteger i = 0;i <= self.plotData.count - 1;++i) {
float RSEFigure = [[self.plotData objectAtIndex:i] floatValue];
if (RSEFigure > max)
max = RSEFigure;
if (RSEFigure < min)
min = RSEFigure;
}
plotStrip.lowerLimit = min;
plotStrip.upperLimit = max;
plotStrip.lineColor = COLOUR_POWDER_BLUE;
[self.view addSubview:_IBOPLotView];
plotStipTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(testGraph:) userInfo:nil repeats:YES];
plotStrip.showDot = YES;
plotStrip.capacity = self.plotData.count;
}
- (void)viewDidLoad {
if (bUsingDynPlot) {
// Dynamically adding to view.
_plotView2 = [[F3PlotStrip alloc] init];
_plotView2.backgroundColor = [UIColor redColor];
_plotView2.frame = CGRectMake(0, 100, 293, 35);
[[self view] addSubview:_plotView2];
[self configurePLotStrip:_plotView2];
} else {
[self configurePLotStrip:_IBOPLotView];
}
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I hope this is easy enough for you to drop in to a new VC. Provided you have the F3PlotStrip.h and .m in your project folder, you'll be good to go - aside from adding a UIView to the VC.
Carl.