NSMutableArray Setter and Getter Methods - ios

I am trying to make an FoodCourt Application. I have 3 MutableArray in AppDelegate.h
// This are declaration and Getter and Setter methods for array.
AppDelegate.h
#property(strong,nonatomic)NSMutableArray* NameArray;
#property(strong,nonatomic)NSMutableArray* QtyArray;
#property(strong,nonatomic)NSMutableArray* KGArray;
-(NSMutableArray*)GetNameNSO;
-(NSMutableArray*)GetQtyNSO;
-(NSMutableArray*)GetKGNSO;
-(void)setNameArray:(NSMutableArray*)NameArray;
-(void)setQtyArray:(NSMutableArray*)QtyArray;
-(void)setKGArray:(NSMutableArray*)KGArray;
I have Implemented Getter and Setter methods in AppDelegate.m
Appdelegate.m
#synthesize NameArray =_NameArray;
#synthesize KGArray =_KGArray;
#synthesize QtyArray=_QtyArray;
-(NSMutableArray*)GetNameNSO
{
if(_NameArray == nil)
{
_NameArray = [[NSMutableArray alloc]init];
NSLog(#"%# GetName FROM HELPER",_NameArray);
return _NameArray;
}
else
{
return _NameArray;
}
}
-(NSMutableArray*)GetQtyNSO
{
if(_QtyArray == nil)
{
_QtyArray = [[NSMutableArray alloc]init];
NSLog(#"%# GetQTY FROM HELPER",_QtyArray);
return _QtyArray;
}
else
{
return _QtyArray;
}
}
-(NSMutableArray*)GetKGNSO
{
if(_KGArray == nil)
{
_KGArray = [[NSMutableArray alloc]init];
NSLog(#"%# GetKG FROM HELPER",_KGArray);
return _KGArray;
}
else
{
return _KGArray;
}
}
-(void)setQtyArray:(NSMutableArray *)QtyArray{
_QtyArray=QtyArray;
NSLog(#"%# SetQty FROM HELPER",_QtyArray);
}
-(void)setNameArray:(NSMutableArray *)NameArray
{
_NameArray =NameArray;
NSLog(#"%# SetName FROM HELPER",_NameArray);
}
-(void)setKGArray:(NSMutableArray *)KGArray
{
_KGArray =KGArray;
NSLog(#"%# SetKG FROM HELPER",_KGArray);
}
Setter Methods works fine as is it should. I am setting my values from FoodController.h in this setter methods and it give me Perfect log with all the values in method.
FoodController.h
AppDelegate *AppAdd;
AppAdd = [[AppDelegate alloc]init];
[AppAdd setNameArray:NameSegue];
[AppAdd setKGArray:KGQtySegue];
[AppAdd setQtyArray:QtySegue];
Above Code is called in prepareForSegue Method. after changing my application view i am trying to fetch this data from Getter method in OrderDetails.m But it give null or no value. I just don't understand why this methods do not work properly. Here's the code of OrderDetails.m file.
OrderDetails.m
AppDelegate *sc;
sc=[[AppDelegate alloc]init];
[DataName addObjectsFromArray:sc.GetNameNSO];
[DataQty addObjectsFromArray:sc.GetQtyNSO];
[DataQty addObjectsFromArray:sc.GetKGNSO];
I just don't understand Why this code is not working, Please Help me out! Thank you.
New Code For Getting Array :
AppDelegate *sc = (AppDelegate *)[UIApplication sharedApplication].delegate;
sc=[[AppDelegate alloc]init];
[DataName addObjectsFromArray:sc.GetNameNSO];
[DataQty addObjectsFromArray:sc.GetQtyNSO];
[DataQty addObjectsFromArray:sc.GetKGNSO];

You should not create the object of App delegate. You should get it by below way.
AppDelegate *sc = (AppDelegate *)[UIApplication sharedApplication].delegate;
[DataName addObjectsFromArray:sc.GetNameNSO];
[DataQty addObjectsFromArray:sc.GetQtyNSO];
[DataQty addObjectsFromArray:sc.GetKGNSO];
Now, sc will have required values. Do not forget to import Appdelegate.h file into the orderdetails.m file.

Related

How properly assign singleton to a variable in iOS?

I have a project written in Objective-C. Inside it I use singleton.
Its declaration is:
+ (id)sharedInstance
{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
I init it inside each class where I use it by this code:
singApp = [XXXsingApplication sharedInstance];
When I run Xcode Analyzer I get following warning:
Instance variable used while 'self' is not set to the result of
'[(super or self) init...]'
Why I get this warning?
I suppose I have some general misunderstanding of matter, because AFAIK it has only single instance and must not be init again to avoid creating several instances?
EDIT:
My init looks like:
-(id)init
{
self = [super init];
// init read-only values
_appSwVersion = APP_SOFT_VERSION;
_appSwDateTime = APP_SOFT_DATETIME;
_websDns = WEBS_DNS;
_testWebsUrl = TEST_WEBS_DNS_URL;
// init properties dictionary
_propListDict = [[NSMutableDictionary alloc] init];
#try {
if (self) {
// load settings
[self loadSettingsFromFile];
// init custom Bundle
[self setCustomBundle];
}
}
#catch (NSException *exception) {
NSLog(#"EXCEPTION\nName-> %#\nDescription-> %#", [exception name], [exception description]);
}
return self;
}
Exceptions are there to catch programming errors. You don't catch and handle exceptions in Objective-C. When an exception happens, you let it crash. This is Objective-C, not Java or C++. You don't handle exceptions, you fix the code.
You should check whether self == nil immediately after calling [super init]. Think about what you are doing: You are assigning to an instance variable which will lead to a crash if self == nil. Sure, there will be cases where people are 100% sure that self cannot be nil. But five lines later, you check whether self == nil. That combination is a clear indication of a bug. If you check, you must check before you assign to an instance variable. If you assign to an instance variable, any check is too late.
Your code should look like this.
-(id)init {
self = [super init];
#try {
if (self) {
// init read-only values
_appSwVersion = APP_SOFT_VERSION;
_appSwDateTime = APP_SOFT_DATETIME;
_websDns = WEBS_DNS;
_testWebsUrl = TEST_WEBS_DNS_URL;
// init properties dictionary
_propListDict = [[NSMutableDictionary alloc] init];
// load settings
[self loadSettingsFromFile];
// init custom Bundle
[self setCustomBundle];
}
} #catch (NSException *exception) {
NSLog(#"EXCEPTION\nName-> %#\nDescription-> %#", [exception name], [exception description]);
}
return self;
}

store key/value in NSDictionary/NSCache which retains data till the app is terminated

I have an app where i want to create a temporary cache which stores key and value.I have done the following
My code is : IN appDelegate.h
#property (strong, nonatomic) NSMutableDictionary *articleCache;
In appDelegate.m
#synthesize articleCache;
and i am calling it in viewController.m
here i need to store the data so that it is cleared only when the app is terminated and is accessible anywhere in the app otherwise.
every time i visit an article i add it to the array so that next time i wont have to fetch it from the network thereby speed up the process.
the Problem is when i set the temp NSMutableDictionary the content gets added but for checkCache.articleCache i get nil.
#define DELEGATE ((AppDelegate*)[[UIApplication sharedApplication]delegate])
this is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//[self loadfeeds];
[self.activityIndi startAnimating];
AppDelegate *checkCache = DELEGATE;
NSString *link = self.webUrl;
//check if the article is already opened and cached before
if([[checkCache.articleCache allKeys] containsObject:link])
{
NSLog(#"Key Exists");
NSString *contents = [checkCache.articleCache valueForKey:link];
[self loadDataOnView:contents];
}
else
{
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
[aQueue addOperationWithBlock:^{
NSLog(#"Key not Exists");
[self startParsing];
}];
}
}
In parser method at the end i do the following i.e to store the article..
but if i add it directly to the checkCache.articleCache nothing is added what should i do?? but it gets added to temp.. do i access the articleCache incorrectly??
AppDelegate *checkCache = DELEGATE;
NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
[checkCache.articleCache setObject:Content forKey:url];
[temp setObject:Content forKey:url];
So how can i solve it??
or Suggest me how can i use NSCache for the same problem. thanks a lot.
It might be a silly question but i m quite new to ios thanks.
In App delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.articleCache = [NSMutableDictionary new];
return YES;
}
When you have to set the object in cache.
AppDelegate *checkCache = DELEGATE;
[checkCache.articleCache setObject:obj forKey:#"Key1"];
To get the object back:
AppDelegate *checkCache = DELEGATE;
id obj = [checkCache.articleCache objectForKey:#"Key1"];
Though there are better ways to get this done.

Saving data from block into an NSMutableDictionary, and blocks in general

I am having a lot of trouble wrapping my head around the best way to use blocks. I am trying to retrieve pedometer data, and the method of accessing the data is a block...
[self.pedometer queryPedometerDataFromDate:yesterday
toDate:midnightOfToday
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"Pedometer is NOT available.");
}
else {
NSLog(#"Steps %#", pedometerData.numberOfSteps);
yesterdaysNumbersLabel.text = [pedometerData.numberOfSteps stringValue];
[pedometerDictionary setValue:[pedometerData.numberOfSteps stringValue] forKey:#"2"];
}
});
}];
Using the above code I am able to get the data, log the data, and update the label on the screen, But I can't figure out how to set the data into an array or dictionary so I can do something else with it.
I understand why the arrays and dictionaries are always null... the blocks are running on a different thread and I am accessing them before the blocks have completed.
Can someone help me get through my head how to do something more with the data.
Update 1:
Right now I have this in .h
#property (strong, atomic) NSMutableDictionary *pedometerDictionary;
and I am synthesizing it in .m and I call this...
[self getNumbersForYesterday];
NSLog(#"Dictionary: %#", pedometerDictionary);
...which runs the above function and immediately tries to log the result. And like I said, I understand all the reasons it is NOT working. I just need to figure out how to change what i am doing to get it working.
Update 2:
This is in .h
#property (strong, atomic) NSMutableDictionary *pedometerDictionary;
and this is in .m
#synthesize pedometerDictionary;
- (id)init {
self = [super init];
if (self != nil) {
self.pedometerDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
and I am using it like this.
[self getNumbersForYesterday];
NSLog(#"Dictionary: %#", self.pedometerDictionary);
to call this.
- (void)getNumbersForYesterday {
[self.pedometer queryPedometerDataFromDate:yesterday
toDate:midnightOfToday
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"Pedometer is NOT available.");
}
else {
NSLog(#"Steps %#", pedometerData.numberOfSteps);
yesterdaysNumbersLabel.text = [pedometerData.numberOfSteps stringValue];
[self.pedometerDictionary setValue:[pedometerData.numberOfSteps stringValue] forKey:#"2"];
}
});
}];
}
If I just wanted to keep all the work in the block I would be fine. What I have come to understand is that since blocks are asynchronous, I am trying to NSLog my dictionary, and the block isn't finished running yet. So, my dictionary is still NULL.
Dollars to donuts, your pedometerDictionary was never created in the first place (or it was, but the declaration isn't in a useful spot).
I.e. where is your line of code that says pedometerDictionary = [[NSMutableDictionary alloc] init];? And where is pedometerDictionary declared? How did you try to NSLog() values from it?
Also, use setObject:forKey:.
It is also odd that it is named pedometerDictionary. That is evidence that it is either declared as a global (which it shouldn't be), a local variable of whatever method contains the above code (which won't work), or you are declaring and using an instance variable directly.
The issue you are having is not a block timing issue, your dictionary should never be nil at worst it would contain no values.
You need to create your dictionary before using it. The appropriate place would be init method for most objects. If you are creating your object in Interface Builder then the method should be awakeFromNib.
To do something with the dictionary you can use an NSTimer or call a method from queryPedometerDataFromDate block handler. The use of #synchronized() directive is an example of how to keep access to the dictionary from overlapping at the same time in a threaded environment. This is not the case in this particular example as you are dispatching on the main thread and NSTimer also runs on the main thread. But should you go threaded #synchronized() would keep you from overlapping access.
#interface HelloWorld : NSObject
#property (retain, atomic) NSMutableDictionary *pedometerDictionary;
#property (retain, nonatomic) NSTimer *timer;
#end
#implementation HelloWorld
#synthesize pedometerDictionary, timer;
...
- (id)init {
self = [super init];
if (self != nil) {
self.pedometerDictionary = [NSMutableDictionary dictionary];
self.timer = [NSTimer timerWithTimeInterval:5.0 target:self selector:#selector(doSomethingInterestingWithDictionary:) userInfo:nil repeats:YES];
}
return self;
}
or
- (void)awakeFromNib {
self.pedometerDictionary = [NSMutableDictionary dictionary];
self.timer = [NSTimer timerWithTimeInterval:5.0 target:self selector:#selector(doSomethingInterestingWithDictionary:) userInfo:nil repeats:YES];
}
...
- (void)getNumbersForYesterday {
[self.pedometer queryPedometerDataFromDate:yesterday
toDate:midnightOfToday
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"Pedometer is NOT available.");
}
else {
NSLog(#"Steps %#", pedometerData.numberOfSteps);
yesterdaysNumbersLabel.text = [pedometerData.numberOfSteps stringValue];
#synchronized (self) {
[self.pedometerDictionary setValue:[pedometerData.numberOfSteps stringValue] forKey:#"2"];
}
[self doSomethingInterestingWithDictionary:nil];
}
});
}];
}
// Will be called when queryPedometerDataFromDate returns and from a timer every 5 seconds.
- (void)doSomethingInterestingWithDictionary:(NSTimer *)aTimer {
#synchronized (self) {
NSLog(#"My days dictionary: %#", self.pedometerDictionary);
}
}

OCMock test code with intermediate variable

I am new to using OCMock. I have the following simplified code I want to test -
#implementation ViewController
- (void)presentSomething:(NSString *)string {
NSLog(#"doSomethingElseWithString - %#", string);
}
- (BOOL)handleResult:(NSString *)result
{
BOOL handled = YES;
NSString *changedString = [result uppercaseString];
[self presentSomething:changedString];
return handled;
}
#end
and I have a test as follows
- (void)testExample {
ViewController *vc = [ViewController new];
id mockViewController = OCMPartialMock(vc);
OCMStub([mockViewController presentSomething:#"1234"]);
BOOL handled = [vc handleResult:#"1234"];
XCTAssertTrue(handled);
OCMVerify([mockViewController presentSomething:#"1234"]);
}
I want to verify presentSomething gets called with the correct argument after I call handleResult.
The test either gives a EXC_BAD_ACCESS while verifying or fails saying the presentSomething method was not invoked.
If I change the handleResult method as follows the test runs and passes.
- (BOOL)handleResult:(NSString *)result
{
BOOL handled = YES;
[self presentSomething:result];
return handled;
}
It seems that intermediate [result uppercaseString] and variable caused the issue. Is this an issue with how I am using OCMock or a bug in OCMock?
Must be trying to do a pointer comparison instead of isEquals. I haven't tried debugging the issue against the source code yet, but there is a workaround:
- (void)testExample
{
ViewController *vc = [ViewController new];
id mockViewController = OCMPartialMock(vc);
OCMExpect([mockViewController presentSomething:#"1234"]);
BOOL handled = [vc handleResult:#"1234"];
XCTAssertTrue(handled);
OCMVerifyAll(mockViewController);
}

iOS Something going wrong between Singleton, Delegate and SocketIO

I have multiple views where I need to handle the network connection of socket.io, so I created singleton class namely MC_SocketHandler. Below is the code of the MC_SocketHandler class.
// MC_SocketHandler.h
#import <Foundation/Foundation.h>
#import "SocketIO.h"
#interface MC_SocketHandler : NSObject <SocketIODelegate>
// SocketIO
//#property (nonatomic) SocketIO *socketConnection;
+ (MC_SocketHandler *) sharedSocketHanderObj;
+ (SocketIO *) initHandShake;
+ (SocketIO *) getSocketConnection;
-(bool) isConnected;
-(void) disConnect;
-(void) fireAgentLeftChat;
#end
// MC_SocketHandler.m
#import "MC_SocketHandler.h"
#import "MC_APIUtility.h"
#implementation MC_SocketHandler
SocketIO *socketConnection = nil;
static MC_SocketHandler *sharedSocketObj = nil;
+ (MC_SocketHandler *) sharedSocketHanderObj {
if (sharedSocketObj == nil)
sharedSocketObj = [[MC_SocketHandler alloc] init];
return sharedSocketObj;
}
+(SocketIO*) initHandShake {
if (socketConnection == nil) {
NSDictionary *headers = [NSDictionary dictionaryWithObjectsAndKeys:[MC_APIUtility getApiToken], #"token", nil];
socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ];
[socketConnection connectToHost:domain onPort:447 withParams:headers];
}
return socketConnection;
}
+ (SocketIO *) getSocketConnection {
return socketConnection;
}
-(bool) isConnected {
if (socketConnection == nil)
return socketConnection.isConnected;
return false;
}
-(void) disConnect {
if (socketConnection != nil && socketConnection.isConnected)
[socketConnection disconnect];
NSLog(#"Disconnected --- %hhd", socketConnection.isConnected );
return;
}
// SocketIO Delegate
-(void) socketIODidConnect:(SocketIO *)socket {
NSLog(#"Socket has Connected....");
}
-(void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet {
NSString *data = packet.data;
NSLog(#"---- didReceoveEvent - data - %#", data);
// Grab data from packet
NSDictionary *dict = packet.dataAsJSON;
NSLog(#"EVENT DATA :- %# DICT :- %#", data, dict);
/*
EVENTS To Listen
onSuccessInit
visitor_info
new_visitor
agent_online
agent_offline
agent_logout
*/
dict = nil;
// Pull out args fro mdict
//NSArray *args = dict[#"args"];
}
-(void) socketIO:(SocketIO *)socket didReceiveMessage:(SocketIOPacket *)packet {
NSLog(#"Rcvd Message - %#", packet.data);
}
-(void) socketIO:(SocketIO *)socket didSendMessage:(SocketIOPacket *)packet {
NSLog(#"Send Msg - %#", packet.dataAsJSON);
}
-(void) socketIO:(SocketIO *)socket onError:(NSError *)error {
NSLog(#"Error - %#", error);
}
-(void) socketIODidDisconnect:(SocketIO *)socket disconnectedWithError:(NSError *)error {
NSLog(#"Disconnected With Error - %#", error);
}
-(void) fireAgentLeftChat {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[MainAppDataObject sharedAppDataObject].activeAgentChatItem.chatSessionId forKey:#"chat_session_id"];
[socketConnection sendEvent:#"agentLeftChat" withData:dict];
return;
}
- (void)dealloc {
socketConnection = nil;
}
#end
Code that I use it in 1 of my views :
// Init SocketIO
SocketIO *socket = [MC_SocketHandler initHandShake];
// Fire Agent Online event
[socket sendEvent:#"setAgentOnline" withData:nil];
Handshake is being done properly, setAgentOnline event is send properly. Other events that I fire are also done properly. BUT,
when socket gets connected thru initHandshake, I believe "Socket has Connected...." should be seen in logs as that is written in socketIODidConnect delegate method. Similarly, I receive event (I see logs of socket.m class), but my delegate method didReceiveEvent is never called. Same way I don't see any logs of any delegate methods.
In initHandShake method only I have set the delegate also :
socketConnection = [[SocketIO alloc] initWithDelegate:(id)self ];
yet why these methods aren't called.
I was also wondering, when I receive events, on different events I got to perform different actions. How will I transfer to particular view (View's obj won't be shared with this to call his method) ? And If I create delegate, then I will have to handle all delegate methods in all views. What's will be the best method to work out with this ? And why this Singleton & delegate methods aren't being linked & called when I have set the delegate. Where am I going wrong ?
Any help, guidance is highly appreciative. Thanks alot.
In SocketIO, you create a SocketIO
Is that right?
In fact called "socketConnection". Am i right?
AT THAT TIME...
you must set the delegate !!!
Essentially, your code must look like this,
socketConnection = make one of these.
socketConnection.delegate = self;
It's possible this is your fundamental problem. I hope it helps!
PS you should, almost certainly, use only properties in iOS development. get rid of your "traditional" variables and use only properties.

Resources