Can't read string from .plist - ios

I have created .plist where I put string which is used for google analytics and the problem is that the string can't be pass to that code in appdelegate.m where is google analytics code.
configuration.plist looks like this :
GAnalytics , string , "XXXXXXXX"
I have create the .h and .m file for it to read it
configuration.h
#import <Foundation/Foundation.h>
#interface Configuration : NSObject
+(instancetype)sharedConfig;
-(NSString *)GoogleAnalyticsID;
#end
configuration.m
#import "Configuration.h"
#interface Configuration ()
#property (strong, nonatomic) NSDictionary *config;
#end
#implementation Configuration
+(instancetype)sharedConfig
{
static Configuration *instance = nil;
if (!instance) {
instance = [[Configuration alloc] init];
}
return instance;
}
-(instancetype)init
{
self = [super init];
if (self) {
NSBundle *bundle = [NSBundle mainBundle];
NSString *configPath = [bundle pathForResource:#"Configuration" ofType:#"plist"];
self.config = [NSDictionary dictionaryWithContentsOfFile:configPath];
}
return self;
}
-(NSString *)GoogleAnalyticsID
{
return self.config[#"GAnalytics"];
}
#end
appdelegate.m
[GAI sharedInstance].trackUncaughtExceptions = YES;
[GAI sharedInstance].dispatchInterval = 20;
[[GAI sharedInstance] trackerWithTrackingId: [[Configuration sharedConfig] GoogleAnalyticsID]];

Related

Objective-C Defining a Global Array for use by several ViewControllers

I've been trying to implement a global NSMutableArray from what I think to be a singleton class that I've implemented.
I can enter ViewController # 2, add and remove objects to the array.
However, when I leave ViewController #2 and come back, the data does not persist, and I have an array with 0 objects.
What do you think I'm doing wrong?
.h
// GlobalArray.h
#interface GlobalArray : NSObject{
NSMutableArray* globalArray;
}
+(void)initialize;
.m
#import "GlobalArray.h"
#implementation GlobalArray
static GlobalArray* sharedGlobalArray;
NSMutableArray* globalArray;
+(void)initialize{
static BOOL initalized = NO;
if(!initalized){
initalized = YES;
sharedGlobalArray = [[GlobalArray alloc] init];
}
}
- (id)init{
if (self = [super init]) {
if (!globalArray) {
globalArray = [[NSMutableArray alloc] init];
}
}
return self;
}
View Controller #2
GlobalArray* myGlobalArray;
myGlobalArray = [[GlobalArray alloc] init];
//Various add and remove code
Thank you for your input.
Following is best approach to share data Globally at Application level. Singleton Class is a key. Singleton is only initialised once, rest of times shared data is returned.
#interface Singleton : NSObject
#property (nonatomic, retain) NSMutableArray * globalArray;
+(Singleton*)singleton;
#end
#implementation Singleton
#synthesize globalArray;
+(Singleton *)singleton {
static dispatch_once_t pred;
static Singleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[Singleton alloc] init];
shared.globalArray = [[NSMutableArray alloc]init];
});
return shared;
}
#end
Following is the way to access/use shared data.
NSMutableArray * sharedData = [Singleton singleton].globalArray;
You create separate instance of GlobalArray in your ViewController#2 with this code:
GlobalArray* myGlobalArray;
myGlobalArray = [[GlobalArray alloc] init];
Instead, you should create accessor method to return your shared instance, something like this:
// GlobalArray.h
#interface GlobalArray : NSObject{
NSMutableArray* globalArray;
}
+(void)initialize;
+(GlobalArray*)sharedInstance;
with implementation:
// GlobalArray.m
// ... your existing code
// accessor method
+(GlobalArray*)sharedInstance
{
return sharedGlobalArray;
}
and then call it from your ViewController#2:
GlobalArray* myGlobalArray = [GlobalArray sharedInstance];
However, using global variables to transfer data between view controllers is bad practice; I suggest you to use more safe methods, create a delegate, for example.
To create a shared global array, if that's really what you want, just put this in the header file:
extern NSMutableArray *myGlobalArray;
and this in your main source file:
NSMutableArray *myGlobalArray;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myGlobalArray = [NSMutableArray new];
}
Use this code for set and get the array views, for adding and removing do it separate in controller itself.
// GlobalArray.h
#interface GlobalArray : NSObject
#property (nonatomic, strong) NSMutableArray* globalArray;
+ (id)sharedManager;
-(NSMutableArray *) getGlobalArray;
-(void) setGlobalArray:(NSMutableArray *)array;
#end
/*-----------------------------------------*/
#import "GlobalArray.h"
#implementation GlobalArray
+ (id)sharedManager {
static GlobalArray *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init{
if (self = [super init]) {
if (!globalArray) {
globalArray = [[NSMutableArray alloc] init];
}
}
return self;
}
-(NSMutableArray *) getGlobalArray{
return self.globalArray;
}
-(void) setGlobalArray:(NSMutableArray *)array{
_globalArray = globalArray;
}
#end
-------------------------
//get array
NSArray * array = [[GlobalArray sharedManager] getGlobalArray];
//set array
[[GlobalArray sharedManager] setGlobalArray:array]
-------------------------

How to call Objective-C instancetype method in Swift?

I have an Objective-C class which looks like this:
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (instancetype)initWithObjHavingData;
#end
and implementation like this
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData{
if (self = [super init]) {
NSString *str = #"This is simple string.";
self.objWithData = [str dataUsingEncoding:NSUTF8StringEncoding];
}
return self;
}
#end
Now I want to call this initWithObjHavingData in Swift
var objData = CustomObjectHavingData()
This returns nil to me. Please help how I can call the above init method here.
You are not supposed to write initializer like that in Objective C. Either you should have it just init or then if you are passing argument in constructor then only you can name it otherwise.
Here is how you can do it,
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (instancetype)initWithObjHavingData:(NSData *)data;
#end
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData:(NSData *)data
{
if (self = [super init]) {
_objWithData = data;
}
return self;
}
#end
In Swift, you can simply call it like this,
let myCustomObject = CustomObjectHavingData(objHavingData: someData)
The name is quite inappropriate though.
If you want to call the init method without any parameter with the requirements I posted in the question, we have to write the init method like this:
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (id)init;
#end
And implement it like this
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData{
if (self = [super init]) {
NSString *str = #"This is simple string.";
self.objWithData = [str dataUsingEncoding:NSUTF8StringEncoding];
}
return self;
}
#end
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData:(NSData *)data
{
if (self = [super init]) {
_objWithData = data;
}
return self;
}
#end
Then, you can call this from swift like this:
var objData = CustomObjectHavingData()
It will by default initialize all the objects.
You can use this :
+ (Common *)sharedInstance
{
static Common *sharedInstance_ = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
sharedInstance_ = [[Common alloc] init];
});
return sharedInstance_;
}
After that for calling
var com_obj : Common!
com_obj = Common.sharedInstance()
com_obj.anyfunc(..)

Trouble setting an NSMutableDictionary inside of another NSMutableDictionary

I need to take information submitted by a user, store that information in an NSMutableDictionary, then store that NSMutableDictionary inside another NSMutableDictionary which is then encoded inside another class. For whatever reason, I can't seem to store the first NSMutableDictionary inside of the other.
I had to slim down the code that's in here due to work rules, so sorry if it seems to be missing anything. I only posted the parts that I'm having trouble with.
UserInfo.h:
#import <Foundation/Foundation.h>
#interface MyPlanInfo : NSObject <NSCoding>
#property (nonatomic, strong) NSMutableDictionary *emergencyDictionary;
#end
UserInfo.m:
#import <Foundation/Foundation.h>
#import "MyPlanInfo.h"
static NSString *emergencyDictionaryKey = #"emergencyDictionaryKey";
#implementation MyPlanInfo
#synthesize emergencyDictionary;
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.emergencyDictionary forKey:emergencyDictionaryKey];
}
#end
infoView.h
#import <UIKit/UIKit.h>
#import "MyPlanInfo.h"
#interface infoView : UIViewController <NSCoding>
{
NSMutableDictionary *emergencyContactInfo;
NSArray *userInfo;
NSArray *userKeys;
NSMutableArray *tempArray;
}
#property (nonatomic, strong) MyPlanInfo *myPlanInfoObject;
-(void)saveUserInfo;
-(void)loadUserInfo;
#end
infoView.m:
#import "infoView.h"
#interface infoView ()
#end
#implementation infoView
static NSString *userInfoKey = #"userInfoKey";
static NSString *userName;
-(void)viewDidLoad
{
[super viewDidLoad];
if(!self.myPlanInfoObject)
{
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
}
[self loadUserInfo];
}
-(void)addToDictionary
{
emergencyContactInfo = [NSMutableDictionary dictionaryWithObjects:userInfo forKeys:userKeys];
if([userInfo count] != 0 || userInfo == nil)
{
self.myPlanInfoObject.emergencyDictionary = [NSMutableDictionary dictionaryWithObject:emergencyContactInfo forKey:userName];
}
[self saveUserInfo];
}
- (void)saveUserInfo
{
NSData *userInfoData = [NSKeyedArchiver archivedDataWithRootObject:self.myPlanInfoObject];
[[NSUserDefaults standardUserDefaults] setObject:userInfoData forKey:userInfoKey];
}
- (void)loadUserInfo
{
NSData *userInfoData = [[NSUserDefaults standardUserDefaults] objectForKey:userInfoKey];
if(userInfoData)
{
self.myPlanInfoObject = [NSKeyedUnarchiver unarchiveObjectWithData:userInfoData];
}
}
#end
In infoView.m, in the addToDictionary method, userInfo is an array of user inputted information, and userKey's is an array of key's. The emergencyContactInfo NSMutableDictionary works just fine, everything is in it, but when I try to set that as an object in a new NSMutableDictionary, for a key, it doesn't work. Everything is nil.
Anyone have any ideas on how what I'm doing wrong?
Edit: If you down vote, please leave a reason as to why so that I can avoid doing whatever I did wrong in the future.
In the following line you’re creating an instance of MyPlanInfo using plain alloc/init:
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
However, at least in the code provided, you haven’t overridden init in MyPlanInfo, but instead, initWithCoder::
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
When you use just plain init, the MyPlanInfo’s emergencyDictionary instance variable will be nil. You should likely add something like the following to MyPlanInfo to override init:
- (id) init
{
if ((self = [super init])) {
emergencyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
That will assure that the newly created MyPlanInfo instance has a proper NSMutableDictionary that can be manipulated from other classes.

no visible #interface eror in objective-c

I can't figure out why the problem described here is happening.
This my student.h:
#import <Foundation/Foundation.h>
#interface Student : NSObject
#property NSString* fName;
#property NSString* lName;
#property NSString* studentId;
#property NSString* phoneNum;
#property NSString* degree;
-(id) init: (NSString*)fName lName:(NSString*)lName sId:(NSString*)sId pn:(NSString*)pn degree: (NSString*) degree;
#end
This is my student.m:
#import "Student.h"
#implementation Student
-(id) init: (NSString*)fName lName:(NSString*)lName sId:(NSString*)sId pn:(NSString*)pn degree: (NSString*) degree
{
self = [super init];
if(self){
self.fName = fName;
self.lName = lName;
self.studentId = sId;
self.phoneNum = pn;
self.degree = degree;
}
return self;
}
#end
And this is my main:
#import <Foundation/Foundation.h>
#import "Student.h"
#import "StudentDB.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Student* ignacio =[[Student alloc] init: #"ignacio" lName: #"cooper" sId: #"123456" pn:#"01234" degree:#"Computer science"];
[[StudentDB instance] addStudents: ignacio];
}
return 0;
}
The error is happening in this line:
Student* ignacio =[[Student alloc] init: #"ignacio" lName: #"cooper" sId: #"123456" pn:#"01234" degree:#"Computer science"];
Here's the entire error:
no visible #interface for 'Student' declares the selector 'init:lName:sId:pn:degree'
Without the StudentDB it works fine. It appears the trouble is there, but I can't find it. Can anyone give me an idea on how I can solve this?
Here are my StudentDB.h and StudentDB.m:
#import "StudentDB.h"
#implementation StudentDB
static StudentDB* instance = nil;
-(id)init
{
self = [super init];
if(self){
self.students = [[NSMutableArray alloc] init];
}
return self;
}
+ (StudentDB*) instance
{
if(instance == nil){
instance = [[StudentDB alloc] init];
}
return instance;
}
-(void) addStudents:(Student *)s
{
[self.students addObject: s];
}
-(Student*) getStudent:(NSString*)sId
{
for(Student* s in self.students)
{
if(s.studentId == sId)
return s;
}
return nil;
}
-(void) deleteStudent:(NSString*)sId
{
for(Student* s in self.students)
{
if(s.studentId == sId){
[self.students removeObject:s];
break;
}
}
}
-(void) updateStudent:(Student*)s
{
[self deleteStudent: s.studentId];
[self addStudents:s];
}
#end
#import <Foundation/Foundation.h>
#import "Student.h"
#interface StudentDB : NSObject
#property NSMutableArray* students;
+(StudentDB*) instance;
-(id)init;
-(void) addStudents:(Student *)s;
-(Student*) getStudent:(NSString*)sId;
-(void) deleteStudent:(NSString*)sId;
-(void) updateStudent:(Student*)s;
#end

NSCache is returning null after restarting project

I'm working with NSCache in Objective-C and Cocoa for iOS. Every time I restart the project, the getCacheRecommend call returns null and I expect it to return a value.
#import <Foundation/Foundation.h>
#class ASJsonDiscoverModel;
#interface ASUserCache : NSObject
+ (ASUserCache *)sharedInstance;
- (void)clear;
- (void)setCacheRecommend:(ASJsonDiscoverModel *)discover;
- (ASJsonDiscoverModel *)getCacheRecommend;
ASJsonDiscoverModel is my custom object class.
#import "ASUserCache.h"
#interface ASUserCache ()
#property (nonatomic,strong) NSCache *cache;
#end
#implementation ASUserCache
+ (ASUserCache *)sharedInstance
{
__strong static ASUserCache *cache = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cache = [[ASUserCache alloc] init];
});
return cache;
}
- (instancetype)init
{
if (self = [super init]) {
_cache = [[NSCache alloc] init];
}
return self;
}
- (void)setCacheRecommend:(ASJsonDiscoverModel *)discover
{
NSString *key = #"channelRecommend";
[_cache removeObjectForKey:key];
[_cache setObject:discover forKey:key];
}
- (ASJsonDiscoverModel *)getCacheRecommend
{
NSString *key = #"channelRecommend";
return [_cache objectForKey:key];
}
- (void)clear
{
if (_cache) {
[_cache removeAllObjects];
}
}
- (NSString *)keyforUserID:(NSString *)userID
{
return [NSString stringWithFormat:#"**%#",userID];
}

Resources