.h
#interface sample : NSObject{
#public
NSData* data;
int val;
}
.m
#implementation sample
-(id) init:(NSData*)data{
if (self = [super init]) {
[self initdata:data];
}
NSLog(#"### self %#",self);
NSLog(#"### self->data %#",self->data);
return self;
}
-(void) initdata:(NSData*) data{
#try{
self->data = [[NSData alloc]initWithData:data];
self->val = 10;
}#catch (NSException* e) {
}
}
}
after returning from initdata method if i print values it's null.
When i install app from xcode to iphone everything works fine but when i install using testflight or itunes all the instance variables are null.
it looks simple, i tried but not able to solve.
Edit:
.m
-(id) init:(NSData*)data{
if (self = [super init]) {
[self initDecodeOffline:data];
}
NSLog(#"### VSF self %#",self);
NSLog(#"### VSF self->SBI %#",self->SBI);
return self;
}
-(void) initDecodeOffline:(NSData*) data{
#try{
self->SBI = [[NSData alloc]initWithData:SBI];
NSLog(#"### VSF SBI-->%#",self->SBI);
}#catch (NSException* e) {
self->inErrorState = true;
}
}
.h
#interface BarCodeProduct : NSObject{
#public
int selectedQuantity;
long rmsCartIndex;
int referenceId;
NSData* SBI;
int maxAllowed;
}
-(id) init:(NSData*)data;
#end
Related
Is there anyway to check the value of 'type' variable with completionHandler.
-(void)sendApiMethod:(NSString*)apiName ApiType:(NSString*)type
{
[SendAPI setAPIWithName:#"APIName" completionHandler:^(NSArray *errors) {
if([type isEqualToString:#"Login"])
{
/// Call Some Other function
}
}];
}
I wrote a small piece of code to verify if works (only reading your question I would say yes as Droppy)
I added all there code in a ViewController in a Simple View App.
some assumption:
- all code there for sake of semplicity ....
- I have added a singleton as it seems You are calling a class method.
- instance method is a bit rough, it simply saves name and block
- I added a typedef for blocks to better reading it.
#import "ViewController.h"
typedef void (^CompletionBlock)(NSArray *errors);
#interface SendAPI : NSObject
-(void)setAPIWithName:(NSString*)name completionHandler: (CompletionBlock)completionHandler;
+(void)setAPIWithName:(NSString*)name completionHandler: (CompletionBlock)completionHandler;
+(SendAPI*)sharedInstance;
#property (strong) CompletionBlock completionBlock;
#property (strong) NSString * name;
#end
#implementation SendAPI : NSObject
static SendAPI * _singleton = nil;
+(SendAPI*)sharedInstance
{
if (_singleton == nil)
{
_singleton = [[SendAPI alloc] init];
}
return _singleton;
}
-(void)setAPIWithName:(NSString*)name completionHandler: (CompletionBlock)completionHandler;
{
self.completionBlock = completionHandler;
self.name = [name copy];
__weak SendAPI * weakRef = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSError* err = [NSError errorWithDomain: #"delayed"
code:1111
userInfo: #{#"info": self.name}
];
weakRef.completionBlock(#[err]);
});
}
+(void)setAPIWithName:(NSString*)name completionHandler: (CompletionBlock)completionHandler;
{
[[SendAPI sharedInstance]setAPIWithName:name completionHandler:completionHandler];
}
#end
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self sendApiMethod:#"HELLO" ApiType: #"Login"];
}
-(void)sendApiMethod:(NSString*)apiName ApiType:(NSString*)type{
[SendAPI setAPIWithName:#"APIName" completionHandler:^(NSArray *errors) {
if([type isEqualToString:#"Login"])
{
/// Call Some Other function
NSLog(#"%#", errors);
}
}];
}
it does LOG correctly
I simplify the code for ask question.
I want to save more class and load class model file.
But now I simplify parameters to one part (lim) in the model(FlightSettingModel.h).
In the FlightSettingModel.h I have set some parameters in here.
FlightSettingModel.h code below:
#import <Foundation/Foundation.h>
#interface FlightSettingModel : NSObject<NSCoding>
// lim property part
#property float limCurrentVal;
#property float limDefaultVal;
#property float limMaxVal;
#property float limMinVal;
// .... other property part
#end
FlightSettingModel.m code below
#import "FlightSettingModel.h"
#interface FlightSettingModel()
{
}
#end
#implementation FlightSettingModel
-(instancetype)init
{
self = [super init];
if(self)
{
self.limDefaultVal = 3.0;
self.limCurrentVal = 4.0;
self.limMaxVal = 10;
self.limMinVal = 0;
// ... other property part value init .....
}
return self;
}
- (void)setFlightSettingToDefaultValue
{
self.limCurrentVal = self.limDefaultVal;
}
- (void) encodeWithCoder: (NSCoder *)encoder
{
[encoder encodeFloat:self.limCurrentVal forKey:#"limCurrentVal"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.limCurrentVal = [decoder decodeFloatForKey:#"limCurrentVal"];
}
return self;
}
#end
Then I have set the singleton SettingData file to initial the FlightSettingModel and other model class.
The SettingData model header like below:
#import <Foundation/Foundation.h>
#import "FlightSettingModel.h"
#interface SettingData : NSObject
#property (nonatomic,strong) FlightSettingModel *flightSettingModel;
+(SettingData*) sharedInstance;
#end
SettingData.m code below:
#import "SettingData.h"
#implementation SettingData
SettingData *sharedInstance;
+(SettingData*) sharedInstance{
if( sharedInstance == nil )
{
sharedInstance = [SettingData new];
}
return sharedInstance;
}
-(id) init{
self = [super init];
if( self )
{
self.flightSettingModel = [FlightSettingModel new];
}
return self;
}
#end
In my storyboard (UI) is like below:
When I click the save button , I want to save the custom class model(FlightSettingModel.h) in the NSKeyedArchiver. When I click the load, I want to load the model from the archiver using NSKeyedUnarchiver and resetting to the slider.
But now,when I drag the slider to other value(ex:10), then I click the save, then I close the app restart the app. I click the load, the slider value will become 0.
I don't know why when I load the value the all value will become 0;
My view controller code .m below:
#import "ViewController.h"
#import "SettingData.h"
#interface ViewController ()
{
NSString *path;
NSString *fileName;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// file manage
path =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
fileName = [path stringByAppendingPathComponent:#"flightFile"];
[self setUIValue];
NSLog(#"---");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)saveAction:(UIButton *)sender {
[NSKeyedArchiver archiveRootObject:[SettingData sharedInstance].flightSettingModel toFile:fileName];
}
- (IBAction)loadAction:(UIButton *)sender {
[SettingData sharedInstance].flightSettingModel = (FlightSettingModel*) [NSKeyedUnarchiver unarchiveObjectWithFile: fileName];
[self setUIValue];
NSLog(#"current Value:%.f",[SettingData sharedInstance].flightSettingModel.limCurrentVal);
}
- (IBAction)sliderChangedAction:(UISlider *)sender {
[SettingData sharedInstance].flightSettingModel.limCurrentVal = sender.value;
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
-(void) setUIValue
{
// setting slider property
self.theSlider.maximumValue = [SettingData sharedInstance].flightSettingModel.limMaxVal;
self.theSlider.minimumValue = [SettingData sharedInstance].flightSettingModel.limMinVal;
self.theSlider.value = [SettingData sharedInstance].flightSettingModel.limCurrentVal;
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
#end
Have anyone know where my problem in my code?
thank you very much.
If you want to download the complete code(the question code) , I have upload in github
This behavior happens because the [SettingData sharedInstance].flightSettingModel.limMaxVal and the [SettingData sharedInstance].flightSettingModel.limMinVal are zero:
-(void) setUIValue
{
// setting slider property
self.theSlider.maximumValue = [SettingData sharedInstance].flightSettingModel.limMaxVal;
// self.theSlider.maximumValue = 0
self.theSlider.minimumValue = [SettingData sharedInstance].flightSettingModel.limMinVal;
// self.theSlider.minimumValue = 0
self.theSlider.value = [SettingData sharedInstance].flightSettingModel.limCurrentVal;
// [SettingData sharedInstance].flightSettingModel.limCurrentVal = 10
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
EDIT: You can fix it by adding this:
- (void) encodeWithCoder: (NSCoder *)encoder {
[encoder encodeFloat:self.limCurrentVal forKey:#"limCurrentVal"];
[encoder encodeFloat:self.limMaxVal forKey:#"limMaxVal"];
[encoder encodeFloat:self.limMinVal forKey:#"limMinVal"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.limCurrentVal = [decoder decodeFloatForKey:#"limCurrentVal"];
self.limMaxVal = [decoder decodeFloatForKey:#"limMaxVal"];
self.limMinVal = [decoder decodeFloatForKey:#"limMinVal"];
}
return self;
}
****What I am trying to do:****
I am attempting to increment the value of [RWGameData sharedGameData].regularBubbleCount by 1 for every second that passes. I have done this successfully. The problem is that I cannot call the following from within AppDelegate#timerCalled. How would I accomplish this?
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
AppDelegate.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
-(void)timerCalled;
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
-(void)timerCalled
{
NSLog(#"Timer Called");
[RWGameData sharedGameData].regularBubbleCount++;
NSLog(#"%li", [RWGameData sharedGameData].regularBubbleCount);
[[RWGameData sharedGameData] save];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerCalled) userInfo:nil repeats:YES];
return YES;
}
#end
PrimaryViewController.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#interface PrimaryViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *regularBubLabel;
#end
PrimaryViewController.m
#import "PrimaryViewController.h"
#interface PrimaryViewController ()
#end
#implementation PrimaryViewController
{
NSString *bubbleImage;
int r;
int i;
}
- (void)viewDidLoad {
[super viewDidLoad];
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
_premiumBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].premiumBubbleCount];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)increment {
if ([#"mysterybubble.png" isEqual:bubbleImage]) {
[RWGameData sharedGameData].premiumBubbleCount += 2;
_premiumBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].premiumBubbleCount];
} else if ([#"megaBubbleLarge30.png" isEqual:bubbleImage]) {
[RWGameData sharedGameData].regularBubbleCount += 50000;
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
} i++;
}
- (IBAction)save {
[[RWGameData sharedGameData] save];
}
- (IBAction)setBubbleStatus {
r = arc4random_uniform(300);
if (r <= 12) {
bubbleImage = #"mysterybubble.png";
[_megaBubbleButton setImage:[UIImage imageNamed:bubbleImage] forState:UIControlStateNormal];
NSLog(#"Roll SUCCESS. [%i] %i", i, r);
} else {
bubbleImage = #"megaBubbleLarge30.png";
[_megaBubbleButton setImage:[UIImage imageNamed:bubbleImage] forState:UIControlStateNormal];
NSLog(#"Roll FAIL. [%i] %i", i, r);
}
}
#end
RWGameData.h
#import <Foundation/Foundation.h>
#interface RWGameData : NSObject <NSCoding>
#property (assign, nonatomic) long regularBubbleCount;
+(instancetype)sharedGameData;
-(void)reset;
-(void)save;
#end
RWGameData.m
#import "RWGameData.h"
#implementation RWGameData
static NSString* const SSGameDataRegularBubbleCountKey = #"regularBubbleCount";
+ (instancetype)sharedGameData {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self loadInstance];
});
return sharedInstance;
}
-(void)reset {
self.regularBubbleCount = 0;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.regularBubbleCount forKey: SSGameDataRegularBubbleCountKey];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (self) {
_regularBubbleCount = [decoder decodeDoubleForKey: SSGameDataRegularBubbleCountKey];
}
return self;
}
+(NSString*)filePath
{
static NSString* filePath = nil;
if (!filePath) {
filePath =
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:#"gamedata"];
}
return filePath;
}
+(instancetype)loadInstance
{
NSData* decodedData = [NSData dataWithContentsOfFile: [RWGameData filePath]];
if (decodedData) {
RWGameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return gameData;
}
return [[RWGameData alloc] init];
}
-(void)save
{
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
}
#end
Either you need the timer to invoke a selector on the PrimaryViewController instead of the AppDelegate, or else the AppDelegate needs to store a reference to the PrimaryViewController in order to call a method on the View Controller that updates the label.
A third (less recommended) method is to send out an NSNotification when the timer fires and have multiple VC's observe and respond to the notification, but that's harder to debug later.
You didn't show the code where the instance of PrimaryViewController gets created, but normally you'd store the reference in a property so you can access it later.
If there are many such view controllers, then the code which creates the ViewControllers (is this the AppDelegate?) should have a property which is an NSMutableArray of view controllers, say myTimerViewControllers. When the timer fires, inside timerCalled, iterate through them and tell each one to update its label.
To really do this with the best pattern, you'd create a simple #protocol with one method (say, handleTimer or updateTimerLabel). Each of the VC's would be declared as supporting this protocol, and the AppDelegate would have code something like:
for(UIViewController<TimerProtocol> *vc in myTimerViewControllers) {
[vc handleTimer];
}
In creating a login screen with static logins I'm trying to store them privately in the following class implementation. When a button creates IONServer objects I initialize it with the function -(void)login:(NSString *)username password:(NSString *)pw and pass it two UITextField.text strings.
If you notice in the init I am testing stuff with NSLog but at every breakpoint it seems like the storedLogins NSMutable array is nil.
IONServer.m
#import "IONServer.h"
#import "IONLoginResult.h"
#interface IONServer ()
#property (nonatomic) NSMutableArray *storedLogins;
#end
#implementation IONServer
-(void)createStoredLogins
{
NSArray *firstUser = #[#"user1",#"pass1"];
NSArray *secondUser = #[#"user2",#"pass2"];
[self.storedLogins addObject:firstUser];
[self.storedLogins addObject:secondUser];
}
-(instancetype)init {
self = [super init];
if (self) {
[self createStoredLogins];
NSLog(#"Stored logins: %#", _storedLogins);
NSLog(#"Stored user: %#", _storedLogins[0][0]);
}
return self;
}
-(void)login:(NSString *)username password:(NSString *)pw
{
NSArray *logins = [[NSArray alloc]initWithArray:_storedLogins];
for (int i = 0; i < [logins count]; i++) {
if (username == logins[i][0] && pw == logins[i][1]) {
IONLoginResult *result = [[IONLoginResult alloc] initWithResult:YES errorMessage:#"Success!"];
self.result = result;
break;
} else {
IONLoginResult *result = [[IONLoginResult alloc] initWithResult:NO errorMessage:#"Error!"];
self.result = result;
}
}
}
-(void)logout
{
}
#end
You need to initialize the array:
-(instancetype)init {
self = [super init];
if (self) {
_storedLogins = [[NSMutableArray alloc] init];
[self createStoredLogins];
NSLog(#"Stored logins: %#", _storedLogins);
NSLog(#"Stored user: %#", _storedLogins[0][0]);
}
return self;
}
I am trying to create a NSMutableDictionary in my class. I have read many post in stackoverflow to understand the difference. But now i am totally confused. So any one correct me , which one is the correct way of initialing a NSMutableDictionary in my class . I have to access this dictiionary in many areas of my application .So suggest me the good way of using the variable initialization ...
/// .h file
#interface ActiveFeeds : NSObject {
}
#property (nonatomic, copy) NSMutableDictionary *invDictionary;
#property (nonatomic, retain) NSString *filePath;
#end
#implementation ActiveFeeds
#synthesize filePath;
#synthesize invDictionary;
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.filePath];
self.invDictionary = [dictionary mutableCopy];
dictionary release];
}
return self;
}
/* And use self.invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[self.invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[self.invDictionary release];
[self.filePath release];
[super dealloc];
}
#end
or like this ....
#interface ActiveFeeds : NSObject {
NSMutableDictionary *invDictionary;
NSString *filePath;
}
#end
#implementation ActiveFeeds
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
invDictionary = [dictionary mutableCopy];
[dictionary release];
}
}
return self;
}
/* And use invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}
#end
Please any one help me to get the correct way of using the variables ....
- (id)initWithFilePath:(NSString *)path{
self = [super init];
if (self != nil){
self.filePath = path;
self.invDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
also
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}