how to collect system info in osx using objective c - objective-c

Is there any method / API defined to collect system info in osx.
I want to write utility which will collect hardware information like CPU,RAM,Network adapter.
Any idea ?
Thanks in advance.

System Profiler is nice and will output an XML for some slow file I/O and also let's depend on another process to complete before getting the desired information. Well if I put it this way, is System Profiler really the best option and answer for this question? I think not (IMO).
Here is how I do it. The header are readonly properties of the private readwrite properties. The category methods are pretty straight forward, but if anyone has a question then post and I will answer.
#import <IOKit/IOKitLib.h>
#import <sys/sysctl.h>
#interface VarSystemInfo ()
#property (readwrite, strong, nonatomic) NSString *sysName;
#property (readwrite, strong, nonatomic) NSString *sysUserName;
#property (readwrite, strong, nonatomic) NSString *sysFullUserName;
#property (readwrite, strong, nonatomic) NSString *sysOSName;
#property (readwrite, strong, nonatomic) NSString *sysOSVersion;
#property (readwrite, strong, nonatomic) NSString *sysPhysicalMemory;
#property (readwrite, strong, nonatomic) NSString *sysSerialNumber;
#property (readwrite, strong, nonatomic) NSString *sysUUID;
#property (readwrite, strong, nonatomic) NSString *sysModelID;
#property (readwrite, strong, nonatomic) NSString *sysModelName;
#property (readwrite, strong, nonatomic) NSString *sysProcessorName;
#property (readwrite, strong, nonatomic) NSString *sysProcessorSpeed;
#property (readwrite, strong, nonatomic) NSNumber *sysProcessorCount;
#property (readonly, strong, nonatomic) NSString *getOSVersionInfo;
- (NSString *) _strIORegistryEntry:(NSString *)registryKey;
- (NSString *) _strControlEntry:(NSString *)ctlKey;
- (NSNumber *) _numControlEntry:(NSString *)ctlKey;
- (NSString *) _modelNameFromID:(NSString *)modelID;
- (NSString *) _parseBrandName:(NSString *)brandName;
#end
static NSString* const kVarSysInfoVersionFormat = #"%#.%#.%# (%#)";
static NSString* const kVarSysInfoPlatformExpert = #"IOPlatformExpertDevice";
static NSString* const kVarSysInfoKeyOSVersion = #"kern.osrelease";
static NSString* const kVarSysInfoKeyOSBuild = #"kern.osversion";
static NSString* const kVarSysInfoKeyModel = #"hw.model";
static NSString* const kVarSysInfoKeyCPUCount = #"hw.physicalcpu";
static NSString* const kVarSysInfoKeyCPUFreq = #"hw.cpufrequency";
static NSString* const kVarSysInfoKeyCPUBrand = #"machdep.cpu.brand_string";
static NSString* const kVarSysInfoMachineNames = #"MachineNames";
static NSString* const kVarSysInfoMachineiMac = #"iMac";
static NSString* const kVarSysInfoMachineMacmini = #"Mac mini";
static NSString* const kVarSysInfoMachineMacBookAir = #"MacBook Air";
static NSString* const kVarSysInfoMachineMacBookPro = #"MacBook Pro";
static NSString* const kVarSysInfoMachineMacPro = #"Mac Pro";
#pragma mark - Implementation:
#pragma mark -
#implementation VarSystemInfo
#synthesize sysName, sysUserName, sysFullUserName;
#synthesize sysOSName, sysOSVersion;
#synthesize sysPhysicalMemory;
#synthesize sysSerialNumber, sysUUID;
#synthesize sysModelID, sysModelName;
#synthesize sysProcessorName, sysProcessorSpeed, sysProcessorCount;
#pragma mark - Helper Methods:
- (NSString *) _strIORegistryEntry:(NSString *)registryKey {
NSString *retString;
io_service_t service =
IOServiceGetMatchingService( kIOMasterPortDefault,
IOServiceMatching([kVarSysInfoPlatformExpert UTF8String]) );
if ( service ) {
CFTypeRef cfRefString =
IORegistryEntryCreateCFProperty( service,
(__bridge CFStringRef)registryKey,
kCFAllocatorDefault, kNilOptions );
if ( cfRefString ) {
retString = [NSString stringWithString:(__bridge NSString *)cfRefString];
CFRelease(cfRefString);
} IOObjectRelease( service );
} return retString;
}
- (NSString *) _strControlEntry:(NSString *)ctlKey {
size_t size = 0;
if ( sysctlbyname([ctlKey UTF8String], NULL, &size, NULL, 0) == -1 ) return nil;
char *machine = calloc( 1, size );
sysctlbyname([ctlKey UTF8String], machine, &size, NULL, 0);
NSString *ctlValue = [NSString stringWithCString:machine encoding:[NSString defaultCStringEncoding]];
free(machine); return ctlValue;
}
- (NSNumber *) _numControlEntry:(NSString *)ctlKey {
size_t size = sizeof( uint64_t ); uint64_t ctlValue = 0;
if ( sysctlbyname([ctlKey UTF8String], &ctlValue, &size, NULL, 0) == -1 ) return nil;
return [NSNumber numberWithUnsignedLongLong:ctlValue];
}
- (NSString *) _modelNameFromID:(NSString *)modelID {
/*!
* #discussion Maintain Machine Names plist from the following site
* #abstract ref: http://www.everymac.com/systems/by_capability/mac-specs-by-machine-model-machine-id.html
*
* #discussion Also info found in SPMachineTypes.plist # /System/Library/PrivateFrameworks/...
* ...AppleSystemInfo.framework/Versions/A/Resources
* Information here is private and can not be linked into the code.
*/
NSDictionary *modelDict = [[NSBundle mainBundle] URLForResource:kVarSysInfoMachineNames withExtension:#"plist"].serialPList;
NSString *modelName = [modelDict objectForKey:modelID];
if ( !modelName ) {
if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineiMac.lowercaseString] ) return kVarSysInfoMachineiMac;
else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacmini.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacmini;
else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacBookAir.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacBookAir;
else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacBookPro.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacBookPro;
else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacPro.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacPro;
else return modelID;
} return modelName;
}
- (NSString *) _parseBrandName:(NSString *)brandName {
if ( !brandName ) return nil;
NSMutableArray *newWords = [NSMutableArray array];
NSString *strCopyRight = #"r", *strTradeMark = #"tm", *strCPU = #"CPU";
NSArray *words = [brandName componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]];
for ( NSString *word in words ) {
if ( [word isEqualToString:strCPU] ) break;
if ( [word isEqualToString:#""] ) continue;
if ( [word.lowercaseString isEqualToString:strCopyRight] ) continue;
if ( [word.lowercaseString isEqualToString:strTradeMark] ) continue;
if ( [word length] > 0 ) {
NSString *firstChar = [word substringToIndex:1];
if ( NSNotFound != [firstChar rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location ) continue;
[newWords addObject:word];
} } return [newWords componentsJoinedByString:#" "];
}
- (NSString *) getOSVersionInfo {
NSString *darwinVer = [self _strControlEntry:kVarSysInfoKeyOSVersion];
NSString *buildNo = [self _strControlEntry:kVarSysInfoKeyOSBuild];
if ( !darwinVer || !buildNo ) return nil;
NSString *majorVer = #"10", *minorVer = #"x", *bugFix = #"x";
NSArray *darwinChunks = [darwinVer componentsSeparatedByCharactersInSet:[NSCharacterSet punctuationCharacterSet]];
if ( [darwinChunks count] > 0 ) {
NSInteger firstChunk = [(NSString *)[darwinChunks objectAtIndex:0] integerValue];
minorVer = [NSString stringWithFormat:#"%ld", (firstChunk - 4)];
bugFix = [darwinChunks objectAtIndex:1];
return [NSString stringWithFormat:kVarSysInfoVersionFormat, majorVer, minorVer, bugFix, buildNo];
} return nil;
}
#pragma mark - Initalization:
- (void) setupSystemInformation {
NSProcessInfo *pi = [NSProcessInfo processInfo];
self.sysName = [[NSHost currentHost] localizedName];
self.sysUserName = NSUserName();
self.sysFullUserName = NSFullUserName();
self.sysOSName = pi.strOperatingSystem;
self.sysOSVersion = self.getOSVersionInfo;
self.sysPhysicalMemory = [[NSNumber numberWithUnsignedLongLong:pi.physicalMemory] strBinarySizeMaxFractionDigits:0];
self.sysSerialNumber = [self _strIORegistryEntry:(__bridge NSString *)CFSTR(kIOPlatformSerialNumberKey)];
self.sysUUID = [self _strIORegistryEntry:(__bridge NSString *)CFSTR(kIOPlatformUUIDKey)];
self.sysModelID = [self _strControlEntry:kVarSysInfoKeyModel];
self.sysModelName = [self _modelNameFromID:self.sysModelID];
self.sysProcessorName = [self _parseBrandName:[self _strControlEntry:kVarSysInfoKeyCPUBrand]];
self.sysProcessorSpeed = [[self _numControlEntry:kVarSysInfoKeyCPUFreq] strBaseTenSpeedMaxFractionDigits:2];
self.sysProcessorCount = [self _numControlEntry:kVarSysInfoKeyCPUCount];
}
- (id) init {
if ( (self = [super init]) ) {
[self setupSystemInformation];
} return self;
}
#end
Enjoy!
P.S. I load all the property values during init so as to avoid multiple system calls && because its cheap && all values should be fairly static.
P.P.S. I also load a MachineNames plist that I created, but I know its my own process only that has access to it and the comment describes where I get the information.

The easiest way is to use the output from the system_profiler command. It also has an -xml option to make the output easy to automatically parse.

The underlying API that I believe System Profiler uses (for at least some of the information it gathers), and that you should use if you want very specific information, is sysctl. It lets you query for individual attributes of the system, including number of CPUs, CPU speed, available RAM, etc.

You can use the scripting bridge in Leopard (or newer) to get the information you want directly from Apple System Profiler.

Related

Objective-C addObject seems to put object into all array indices

I am trying to learn how to make simple classes.
So far I am not getting the results expected using addObject and my class.
Here is what I have:
In my view controller:
#import "onoffclass.h"
In its viewDidLoad:
NSMutableArray *inTable;
onoffclass *therec;
onoffclass *readrec;
inTable = [NSMutableArray array];
therec = [[onoffclass alloc]init];
readrec = [[onoffclass alloc]init];
for (int lop=0;lop<3;lop++){
therec.parsedID = [NSString stringWithFormat:#"%i",lop];
[inTable addObject:therec];
NSLog(#"lop=%i onoff.parsedID=%#",lop,therec.parsedID);
for (int z=0;z<[inTable count];z++){
readrec = inTable[z];
NSLog(#" inTable[%i] parsedID=%#",z,readrec.parsedID);
}
}
In my onoffclass.h:
#interface onoffclass : NSObject
#property NSString *parsedID;
#property NSString *parsedOn;
#property NSString *parsedOff;
#property NSString *parsedAdj;
#property NSString *parsedRoom;
#property NSString *parsedBuilding;
#property NSString *parsedWho;
#property NSString *parsedInfo;
#property NSString *parsedBillable;
-(onoffclass*)initWithSomeString: (NSString*)blah AndSomeNum: (int)num;
-(NSString*)description;
#end
In my onoffclass.m:
#import <Foundation/Foundation.h>
#import "onoffclass.h"
#implementation onoffclass {
NSString *_parsedID;
NSString *_parsedOn;
NSString *_parsedOff;
NSString *_parsedAdj;
NSString *_parsedRoom;
NSString *_parsedBuilding;
NSString *_parsedWho;
NSString *_parsedInfo;
NSString *_parsedBillable;
}
-(onoffclass*)initWithSomeString: (NSString*)blah AndSomeNum: (int)num {
self = [super init];
_parsedID = blah;
_parsedOn = #"on";
_parsedOff = #"off";
_parsedAdj = #"adj";
_parsedRoom = #"room";
_parsedBuilding = #"building";
_parsedWho = #"who";
_parsedInfo = #"info";
_parsedBillable = #"billable";
return self;
}
-(NSString*)description {
return [NSString stringWithFormat: #"%#", _parsedID];
}
#end
Here is the output:
lop=0 onoff.parsedID=0
inTable[0] parsedID=0
lop=1 onoff.parsedID=1
inTable[0] parsedID=1
inTable[1] parsedID=1
lop=2 onoff.parsedID=2
inTable[0] parsedID=2
inTable[1] parsedID=2
inTable[2] parsedID=2
Why does it appears that addObject is updating all array indices and how do I fix this?
Thanks,
Dale
You are creating one instance of onoffclass (by the way class names should start with a capital letter) then you are adding the same instance again and again in the loop. Since classes are reference types changing a property affects all occurrences of the same instance.
Solution is to put the line to create an instance in the loop
for (int lop = 0; lop < 3; lop++) {
therec = [[onoffclass alloc] init];
...

Enumerate through objects properties

Here is an example of how the properties of a javascript object can be enumerated through. I noticed that the loop construct used was a for...in loop. Objective-C also has a for...in loop, so is the same behavior possible in Objective-C?
#interface Bar : NSObject
#property (nonatomic) NSString * stringA;
#property (nonatomic) NSString * stringB;
#property (nonatomic) NSString * stringC;
#end
int main(int argc, const char *argv[]) {
Bar obj = [[Bar alloc] init];
obj.stringA = #"1";
obj.stringB = #"2";
obj.stringC = #"3";
for (NSString *property in obj) {
NSLog(#"%#", property);
}
}
Is this possible with Objective-C? If not, is there an alternative that would mimmic this behavior of iterating through an objects properties?
Short answer: yes it is possible.
Here's some sample code of what you're trying to achieve.
Header
#interface Bar : NSObject
#property (nonatomic, retain) NSString *stringA;
#property (nonatomic, retain) NSString *stringB;
#property (nonatomic, retain) NSString *stringC;
#end
Main
#implementation Bar
// don't forget to synthesize
#synthesize stringA, stringB, stringC;
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
unsigned int numberOfProperties = 0;
objc_property_t *propertyArray = class_copyPropertyList([Bar class], &numberOfProperties);
for (NSUInteger i = 0; i < numberOfProperties; i++)
{
objc_property_t property = propertyArray[i];
NSString *letter = [[NSString alloc] initWithUTF8String:property_getName(property)];
NSString *attributesString = [[NSString alloc] initWithUTF8String:property_getAttributes(property)];
NSLog(#"Property %# attributes: %#", letter, attributesString);
}
free(propertyArray);
}
}
Let me know if you have any questions.
Fast enumeration
Bar *obj = [[Bar alloc] init];
// ...
for (id elem in obj) {
...
}
requires that the class Bar conforms to the NSFastEnumeration Protocol, i.e. it must implement the
countByEnumeratingWithState:objects:count:
method. (This is the case for all Objective-C collection classes such asNSArray, NSDictionary, NSSet.)
So the direct answer to your question is no, you cannot use the fast enumeration syntax for (... in ...) to enumerate all properties of an arbitrary class.
However, it is possible to implement the fast enumeration protocol for a custom class.
Examples how this is done can be found here
https://developer.apple.com/library/mac/samplecode/FastEnumerationSample/Introduction/Intro.html
http://www.cocoawithlove.com/2008/05/implementing-countbyenumeratingwithstat.html

Get NSMutableDictionary from Singleton?

I created a singleton class in order to share an object inside my program. Here's the code:
SelectedRow.h
#import <Foundation/Foundation.h>
#import "TableEntry.h"
#interface SelectedRow : NSObject {
TableEntry *rowValue;
}
#property (nonatomic, retain) TableEntry *rowValue;
+ (id)sharedManager;
- (void)setVariable:(TableEntry*)value;
#end
and SelectedRow.m
#import "SelectedRow.h"
#import "TableEntry.h"
#implementation SelectedRow
#synthesize rowValue;
+ (id)sharedManager {
static SelectedRow *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
rowValue = [[TableEntry alloc] init];
}
return self;
}
- (void)setVariable:(TableEntry*)value {
rowValue = value;
}
#end
while TableEntry.h
#import <Foundation/Foundation.h>
#interface TableEntry : NSObject {
#private
NSString *videoId;
NSString *videoCategory;
NSString *videoTitle;
NSString *videoDescription;
NSDate *videoDate;
NSMutableArray *videoRelatedVideos;
NSDictionary *videoAdditionalInformation;
NSString *videoAccessControl;
NSArray *videoFields;
NSMutableDictionary *days;
NSMutableDictionary *views;
NSMutableDictionary *watchtime;
NSMutableDictionary *subscribers;
NSMutableDictionary *shares;
}
#property (copy) NSString *videoId;
#property (copy) NSString *videoCategory;
#property (copy) NSString *videoTitle;
#property (copy) NSString *videoDescription;
#property (copy) NSMutableArray *videoRelatedVideos;
#property (copy) NSDictionary *videoAdditionalInformation;
#property (copy) NSArray *videoFields;
#property (copy) NSString *videoAccessControl;
#property (copy) NSDate *videoDate;
#property (copy) NSMutableDictionary *days;
#property (copy) NSMutableDictionary *views;
#property (copy) NSMutableDictionary *subscribers;
#property (copy) NSMutableDictionary *shares;
#property (copy) NSMutableDictionary *watchtime;
- (id)setId:(NSString*)Id setCategory:(NSString*)Category setDate:(NSDate*)date setTitle:(NSString*)title setDescription:(NSString*)description setRelatedVideos:(NSMutableArray*)relatedVideos setAdditionalInformation:(NSDictionary*)additionalInformation setAccessControl:(NSString*)accessControl setFields:(NSArray*)fields setDays:(NSMutableDictionary*)days setViews:(NSMutableDictionary*)views setSubscribers:(NSMutableDictionary*)subscribers setShares:(NSMutableDictionary*)shares setWatchtime:(NSMutableDictionary*)watchtime;
- (NSString*)extractId;
- (NSString*)extractCategory;
- (NSString*)extractTitle;
- (NSString*)extractDescription;
- (NSMutableArray*)extractRelatedVideos;
- (NSDictionary*)extractAdditionalInformationVideos;
- (NSDictionary*)extractAccessControlVideos;
- (NSArray*)extractFields;
- (NSMutableDictionary*)extractDays;
- (NSMutableDictionary*)extractViews;
- (NSMutableDictionary*)extractSubscribers;
- (NSMutableDictionary*)extractShares;
- (NSMutableDictionary*)extractWatchtime;
#end
and TableEntry.m
- (id)init {
self = [super init];
if (self) {
videoId = #"9bZkp7q19f0";
videoCategory = #"Music";
videoTitle = #"Demo Title";
videoDescription = #"Demo description";
videoDate = [NSDate date];
videoAdditionalInformation = [NSDictionary alloc];
videoRelatedVideos = [NSMutableArray alloc];
videoAccessControl = #"demo accesControl";
videoFields = [NSArray alloc];
days = [NSMutableDictionary alloc];
views = [NSMutableDictionary alloc];
shares = [NSMutableDictionary alloc];
subscribers = [NSMutableDictionary alloc];
watchtime = [NSMutableDictionary alloc];
}
return self;
}
- (id)setId:(NSString*)Id setCategory:(NSString*)Category setDate:(NSDate*)date setTitle:(NSString*)title setDescription:(NSString*)description setRelatedVideos:(NSMutableArray*)relatedVideos setAdditionalInformation:(NSDictionary*)additionalInformation setAccessControl:(NSString*)accessControl setFields:(NSArray*)fields setDays:(NSMutableDictionary*)Days setViews:(NSMutableDictionary*)Views setSubscribers:(NSMutableDictionary*)Subscribers setShares:(NSMutableDictionary*)Shares setWatchtime:(NSMutableDictionary*)Watchtime {
videoId = Id;
videoCategory = Category;
videoDate = date;
videoTitle = title;
videoDescription = description;
videoRelatedVideos = relatedVideos;
videoAccessControl = accessControl;
videoAdditionalInformation = additionalInformation;
videoFields = fields;
days = Days;
views = Views;
subscribers = Subscribers;
watchtime = Watchtime;
shares = Shares;
return self;
}
- (NSString*)extractId {
return self.videoId;
}
- (NSString*)extractCategory{
return self.videoCategory;
}
- (NSString*)extractTitle{
return self.videoTitle;
}
- (NSString*)extractDescription{
return self.videoDescription;
}
- (NSMutableArray*)extractRelatedVideos{
return self.videoRelatedVideos;
}
- (NSString*)extractAccessControlVideos{
return self.videoAccessControl;
}
- (NSDictionary*)extractAdditionalInformationVideos{
return self.videoAdditionalInformation;
}
- (NSArray*)extractFields{
return self.videoFields;
}
- (NSMutableDictionary*)extractDays{
return self.days;
}
- (NSMutableDictionary*)extractSubscribers{
return self.subscribers;
}
- (NSMutableDictionary*)extractWatchtime{
return self.watchtime;
}
- (NSMutableDictionary*)extractShares{
return self.shares;
}
- (NSMutableDictionary*)extractViews{
return self.views;
}
#end
I can extract any values from the singleton with:
SelectedRow *selectedRow = [SelectedRow sharedManager];
NSString *videoID = [selectedRow.rowValue extractId];
the problem arises with any NSMutableDictionary. If I try:
SelectedRow *selectedRow = [SelectedRow sharedManager];
NSMutableDictionary *days = [selectedRow.rowValue extractDays];
or with any other NSMutableDictionary I get this error:
[NSMutableDictionary count]: method sent to an uninitialized mutable dictionary object
what I'm I doing wrong? Thanks
The [NSMutableDictionary alloc] call allocates the space for NSMutableDictionary, but it does not initialize it.
Replace it with [NSMutableDictionary dictionary] to fix the problem. Same goes for your NSArray and NSMutableArray objects (replace them with [NSMutable array] and [NSMutableArray array]).
The videoAdditionalInformation of type NSDictionary should be initialized to nil, though, because NSDictionary objects are immutable. If you are planning to set it to some dictionary later on, you might as well keep it nil on initialization.
In addition, you should reconsider the use of copy: it makes sense for NSString objects, but it hardly makes sense on NSMutableDictionary objects.

Objective-C, set and get variables in class object which is stored in NSArray

I am trying to write my own class storing data about libraries and then store each object in an NSArray.
My interface:
#import <Foundation/Foundation.h>
#interface LibraryInfo : NSObject
{
NSString* name;
NSString* address;
NSString* link;
NSString* coordinates;
}
- (NSString*) getName;
- (NSString*) getAddress;
- (NSString*) getLink;
- (NSString*) getCoordinates;
- (void) setName: (NSString*)input;
- (void) setAddress: (NSString*)input;
- (void) setLink: (NSString*)input;
- (void) setCoordinates: (NSString*)input;
#end
My implementation:
#import "LibraryInfo.h"
#implementation LibraryInfo
- (void) setName: (NSString*)input
{
name = input;
}
- (void) setAddress: (NSString*)input
{
address = input;
}
- (void) setLink: (NSString*)input
{
link = input;
}
- (void) setCoordinates: (NSString*)input
{
coordinates = input;
}
- (NSString*) getName {
return name;
}
- (NSString*) getAddress {
return address;
}
- (NSString*) getLink {
return link;
}
- (NSString*) getCoordinates {
return coordinates;
}
#end
I write and store each object in the NSArray, like so:
LibraryInfo *library = [[LibraryInfo alloc] init];
[library setName:( ( name != nil && name.length > 0 ) ? name : #"No Name" )];
[library setAddress:( ( address != nil && address.length > 0 ) ? address : #"No Address" )];
[library setLink:( ( link != nil && link.length > 0 ) ? link : #"No Link" )];
[library setCoordinates:( ( coordinate != nil && coordinate.length > 0 ) ? coordinate : #"No Coordinates" )];
[libraries addObject: library];
Where 'libraries' is an NSArray.
Then I try to read the values like so:
cell.textLabel.text = [[ libraries objectAtIndex:indexPath.row ] getName ];
cell.detailTextLabel.text = [[ libraries objectAtIndex:indexPath.row ] getAddress ];
I think it may be something to do with the setting of the values, or maybe they are not properly stored or retained, but I get the following error and a marker by my 'setName' method
when the App 'crashes' and pauses:
self LibraryInfo *const 0x068a1760
input NSString * 0x068a3550
name NSString * 0x00000000
How do I fix this? I'm using Xcode 4.3 so no releases/retains needed.
You need to declare properties. IVars aren't going to store your data the way you're expecting
LibraryInfo.h
#interface LibraryInfo : NSObject
#property (nonatomic, strong) NSString* name;
#property (nonatomic, strong) NSString* address;
#property (nonatomic, strong) NSString* link;
#property (nonatomic, strong) NSString* coordinates;
LibraryInfo.m
#implementation LibraryInfo
#synthesize name;
#synthesize address;
#synthesize link;
#synthesize coordinates;
Then creating libraries would be simple
LibraryInfo *library = [[LibraryInfo alloc] init];
library.name = (name.length > 0 ? name : #"No Name");
library.address = (address.length > 0 ? address : #"No Address")
library.link = (link.length > 0 ? link : #"No Link")
library.coordinates = (coordinates.length > 0 ? coordinates : #"No Coordinates")
Then in your TableView cell.
cell.textLabel.text = [libraries objectAtIndex:indexPath.row].name;
cell.detailTextLabel.text = [libraries objectAtIndex:indexPath.row].address;

Unable to save NSMutableArray of my class to file (IOS)

Can't find out why my code doesn't work. Please help someone.
I created my own class, implemented NSCoding protocol. Do not know what i miss or wrong.
Here is saving code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"Currency.plist"];
Item * item = [[Item alloc] init];
item.x = 3; item.y = 5; item.type = (TType) 3; item.isSelected = NO;
NSMutableArray * array = [[NSMutableArray alloc] init];
[array addObject:item];
[array fileName atomically:YES] // ( Doesn't Save the file ,returns NO);
Here is the code of my class
*.h*
#import <Foundation/Foundation.h>
enum TType
{
kNone = 0,
KFirst = 1,
....
};
#interface Item : NSObject <NSCoding>{
}
#property (nonatomic) int x;
#property (nonatomic) int y;
#property (nonatomic) enum TType type;
#property (nonatomic) BOOL isSelected;
#end
.m
#implementation Item
#synthesize x, y , type , isSelected;
#pragma mark NSCoding Protocol
- (void)encodeWithCoder:(NSCoder *)encoder;
{
[encoder encodeInt32:[self x] forKey:#"x"];
[encoder encodeInt32:[self y] forKey:#"y"];
[encoder encodeInt32:[self type] forKey:#"type"];
[encoder encodeBool:[self isSelected] forKey:#"isSelected"];
}
- (id)initWithCoder:(NSCoder *)decoder;
{
if ( ![super init] )
return nil;
[self setX:[decoder decodeInt32ForKey:#"x"]];
[self setY:[decoder decodeInt32ForKey:#"y"]];
[self setType:(TType)[decoder decodeInt32ForKey:#"color"]];
[self setIsSelected:[decoder decodeBoolForKey:#"isSelected"]];
return self;
}
#end
I think you'll find your answer at: objects conforming to nscoding will not writetofile
i.e. you can't serialize your Item class to a property list, since it isn't a property list object (NSString, NSData, NSArray, or NSDictionary).
See the documentation for writeToFile:atomically::
This method recursively validates that all the contained objects are property list objects before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.