Help Needed personal project


#1

I have a small program that I want to complete. I’d like to re-create a small application that I created on the windows platform using Visual Basic.

I know that I shouldn’t feel overwhelmed but I do and struggle to make any progress.

The original program is fairly simple on the surface. It is a program that will generate a Garmin FIT file. The FIT file type format is weight scale data format that is used to upload data to the GarminConnect website. On the surface the user interface appears fairly simple.

A field to enter the weight in either KG or pounds, enter in either will populate the other field with the conversion. A slider that can adjust pounds or Kilo values.
A field to enter the percent of body fat or use a slider to adjust the values.
A Date Picker field to set the date, a button to set the date to todays date.
A button to generate the FIT file.

On launch I’d like the fields to populate with the last values that were last active when the user last generated a FIT file.
I am struggling to just create the user interface. Do I need to make a class file where I store the date, weight and fat percentage. The FIT file uses a date format that is Seconds since the start of 1980 or 23:59:59 Dec 31 1979. I won’t go into the full details of the FIT file format, other than some parts are stored in BigEndian and some parts in LittleEndian. I mentioned the seconds since a date… There is also a requirement to generate a CRC16 for the finished file and add the result as the last two characters of the file.

So behind the scenes I want to build a fairly specific file format with a checksum built in.

For now I want the app to just generate the data, a future possiblity would be an array that stores the data with the ability to locally plot the information and still generate the FIT file format for garminconnect.com, but that is only after I get the program working. So do I plan with a class file in mind now so I can have an array of data points and date vlaues?

When the FIT file is uploaded to a users profile on garminconnect.com, the data is added to the users fitness area in an online plot of weight and body fat and other possible scale values, for now I just want to implement Weight and percent of bodyfat.

If there is anyone that could help me to get started just getting the user interface working, so that I can get access to the data I would appreciate it. I am fairly confident I can get the parts working behind the scenes that do the CRC calculation and build the string in the format of the FIT file. Saving that file out might still be a problem as I have never saved a string out to a file yet on xcode.
Anyone want to help?
Thanks,
Brian Heiland


#2

Brian,

To me your application sounds a lot like the RaiseMan exercise we do in the book, in Chapters 8-10 (and beyond). Have you done the exercises in those chapters? If you are new to Cocoa I would suggest going the route described in those chapters, and not tackling Core Data until you are more comfortable.

As for generating the FIT file, this will be a little trickier to do, but basically it is going to require that you take advantage of Objective-C being built on C – C’s buffer manipulation is perfect for this sort of thing. You can use an NSSavePanel to let the user choose where to save the FIT file (check out Chapter 18, which covers NSOpenPanel, a subclass of NSSavePanel). Take advantage of nil-targeted actions (Chapter 21) to create an action on your document that starts the export process, and connect an “Export FIT” menu item to this action. You can write the data using C file functions (fopen(), fwrite(), fclose()), or you can take advantage of NSData’s methods for writing data to a file.

Cocoa is very different from VB and almost every other GUI platform, but once you get settled in it it’s very rewarding to work in. If you haven’t been working through the book’s exercises I would strongly recommend that to get you the practice with the tools that you will need to start to think about how to design your own app… and it does take practice!

Good luck!

Adam


#3

I have worked through many of the exercises. I think I reached a point where everything was starting to become a blur.

I’ll look at the raiseman again. I wanted to first create a project without the use of the array controller. I was not sure how to connect the user interface elements to the code, while maintaining MVC design.

For example, The weight in KG text box, the Weight in Pounds text box or the weight slider. Changing any of the three on the UI should update the other two. Should this use setters and getters, @synthesize, bindings or a combination of these, Key value observing maybe.

I’d like to begin the project just getting the UI to gather the information into the variables that I need. Step two will be to write the files out to a text file. Step three figure out the particulars of making the FIT file format and write that file step 4 will be to make a version that stores multiple entries locally in an array. Step 5 if I get there would be to plot the information in a UI window.

I’m going to review the chapters for raiseman, but I believe it uses an array controller. I was hoping move onto an array controller version later.
I am very new to Cocoa and feel this project is fairly simple yet challenging at the same time.


#4

I have worked for several hours trying to figure this out without success. So I will post my code so far.

As you can see I just have two text fields, a slider and two labels.
I have tried to create a class file for my data called DataStore.

[code]//
// DataStore.h
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DataStore : NSObject{
float weightKG;
}
-(id)init;
@property (readwrite) float weightKG;
@end[/code]
Implimentation

[code]//
// DataStore.m
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import “DataStore.h”

@implementation DataStore
@synthesize weightKG;

-(id) init {
self = [super init];
if (self) {
[self setWeightKG:99.0];

}
return self;

}

@end[/code]

I created an AppController class as well

[code]//
// AppController.h
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import <Foundation/Foundation.h>

#import “DataStore.h”
@class DataStore;

@interface AppController : NSObject{
}
@property (assign) IBOutlet NSTextField *kilosTextField;
@property (assign) IBOutlet NSTextField *poundsTextfield;
@property (assign) IBOutlet NSSlider *kiloSlider;
-(void)updateUserInterface;

  • (IBAction)floatValueWeightInput:(id)sender;

@end[/code]

[code]//
// AppController.m
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import “AppController.h”
#import “DataStore.h”

@implementation AppController
@synthesize kilosTextField;
@synthesize poundsTextfield;
@synthesize kiloSlider;

-(id)init
{
self = [super init];
if(self) {
DataStore *dStore = [[DataStore alloc] init];
[dStore setWeightKG:100];
[self updateUserInterface];
}
return self;

}
-(void)awakeFromNib
{

}
-(IBAction)floatValueWeightInput:(id)sender{
NSString *senderName = nil;
float newValue = [sender floatValue];
if (sender == kilosTextField) {
[dStore setWeightKG];
[self updateUserInterface];
senderName = @“kilosTextField”;
}
}

  • (void)updateUserInterface{
    float weightKG = [dStore weightKG];
    [[self kilosTextField] setFloatValue];
    [self.poundsTextfield setFloatValue:(weightKG * 2.2046)];
    [self.kiloSlider setFloatValue:(weightKG )];

}

@end[/code]

the AppDelegate is un-modified

[code]//
// MyTestAppDelegate.h
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface MyTestAppDelegate : NSObject

@property (assign) IBOutlet NSWindow *window;

@end[/code]

[code]//
// MyTestAppDelegate.m
// MyTest
//
// Created by Brian Heiland on 12/22/11.
// Copyright © 2011 MyCompanyName. All rights reserved.
//

#import “MyTestAppDelegate.h”

@implementation MyTestAppDelegate

@synthesize window = _window;

  • (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
    // Insert code here to initialize your application
    }

@end[/code]

In the AppController you can see that in the -(id)init I am trying to initialize *dStore as type DataStore, and I even set a value for the weightKG after the init.
Where I run into a problem is that I can’t use dStore to try to change the value with floatValueWeightInput or access dStore in updateUserInterface.

[dStore setWeightKG]; reports use of undefined identifier ‘dStore’ Yet I am initializing dStore in the init method.
I feel really silly asking this question, but it is a big stumbling block for me and hope that someone can help.
Thanks.


#5

In looking at the code I think the issue is fairly simple. You need to create dStore as an instance variable. As it is, you are defining it as a local variable within -init. So modify AppController.h to look more like this:

@interface AppController : NSObject {
    DataStore *dStore;
}

and remove the “DataStore *” from in front of where you initialize DataStore:

-(id)init
{
    self = [super init];
    if(self) {
        dStore = [[DataStore alloc] init];
        [dStore setWeightKG:100];
        [self updateUserInterface];
    }
    return self;
}

Do you see the distinction between the two (local vs instance variable)?

Adam