New a better way of initializing classes and objects - iphone

Here is a code that I thought of to initialize my picker with. Is there a better way to write this?
The interface
#interface roomsClass : NSObject {
NSInteger roomID;
NSString *name;
NSString *desc;
}
#property (nonatomic, readwrite) NSInteger roomID;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *desc;
#end
#interface typesClass : NSObject {
NSInteger typeID;
NSString *name;
}
#property (nonatomic, readwrite) NSInteger typeID;
#property (nonatomic, copy) NSString *name;
#end
The implementation
NSMutableArray *tempArrayA = [[NSMutableArray alloc] init];
self.roomsArray = tempArrayA;
[tempArrayA release];
roomsClass *tempObjA1 = [[roomsClass alloc] init];
tempObjA1.roomID = 202;
tempObjA1.name = #"MH202";
tempObjA1.desc = #"Lab";
[roomsArray addObject:tempObjA1];
[tempObjA1 release];
roomsClass *tempObjA2 = [[roomsClass alloc] init];
tempObjA2.roomID = 207;
tempObjA2.name = #"MH207";
tempObjA2.desc = #"Office";
[roomsArray addObject:tempObjA2];
[tempObjA2 release];
roomsClass *tempObjA3 = [[roomsClass alloc] init];
tempObjA3.roomID = 208;
tempObjA3.name = #"MH208";
tempObjA3.desc = #"Office";
[roomsArray addObject:tempObjA3];
[tempObjA3 release];
roomsClass *tempObjA4 = [[roomsClass alloc] init];
tempObjA4.roomID = 209;
tempObjA4.name = #"MH209";
tempObjA4.desc = #"Lab";
[roomsArray addObject:tempObjA4];
[tempObjA4 release];
roomsClass *tempObjA5 = [[roomsClass alloc] init];
tempObjA5.roomID = 210;
tempObjA5.name = #"MH210";
tempObjA5.desc = #"Lab";
[roomsArray addObject:tempObjA5];
[tempObjA5 release];
roomsClass *tempObjA6 = [[roomsClass alloc] init];
tempObjA6.roomID = 211;
tempObjA6.name = #"MH211";
tempObjA6.desc = #"Office";
[roomsArray addObject:tempObjA6];
[tempObjA6 release];
NSMutableArray *tempArrayB = [[NSMutableArray alloc] init];
self.typesArray = tempArrayB;
[tempArrayB release];
typesClass *tempObjB1 = [[typesClass alloc] init];
tempObjB1.typeID = 1;
tempObjB1.name = #"Desktop";
[typesArray addObject:tempObjB1];
[tempObjB1 release];
typesClass *tempObjB2 = [[typesClass alloc] init];
tempObjB2.typeID = 2;
tempObjB2.name = #"Laptop";
[typesArray addObject:tempObjB2];
[tempObjB2 release];
typesClass *tempObjB3 = [[typesClass alloc] init];
tempObjB3.typeID = 3;
tempObjB3.name = #"Monitor";
[typesArray addObject:tempObjB3];
[tempObjB3 release];
typesClass *tempObjB4 = [[typesClass alloc] init];
tempObjB4.typeID = 4;
tempObjB4.name = #"Server";
[typesArray addObject:tempObjB4];
[tempObjB4 release];
typesClass *tempObjB5 = [[typesClass alloc] init];
tempObjB5.typeID = 5;
tempObjB5.name = #"Printer";
[typesArray addObject:tempObjB5];
[tempObjB5 release];
typesClass *tempObjB6 = [[typesClass alloc] init];
tempObjB6.typeID = 6;
tempObjB6.name = #"Projector";
[typesArray addObject:tempObjB6];
[tempObjB6 release];
typesClass *tempObjB7 = [[typesClass alloc] init];
tempObjB7.typeID = 7;
tempObjB7.name = #"Other";
[typesArray addObject:tempObjB7];
[tempObjB7 release];
if (roomPicker == nil) {
roomPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
roomPicker.delegate = self;
roomPicker.dataSource = self;
roomPicker.showsSelectionIndicator = YES;
roomPicker.transform = CGAffineTransformMakeScale(1.0, 1.0);
roomPicker.tag = kRoomPicker;
}
txtRoomID.inputView = roomPicker;
if (typePicker == nil) {
typePicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
typePicker.delegate = self;
typePicker.dataSource = self;
typePicker.showsSelectionIndicator = YES;
typePicker.transform = CGAffineTransformMakeScale(1.0, 1.0);
typePicker.tag = kTypePicker;
}
txtTypeID.inputView = typePicker;
The idea is to have the picker show some text, but when the user selects the text on the UIPickerView, the integer value/id of the selection be placed in the UITextField, rather than the text the user sees.
I am using iOS 4.3.1 on the device, with 4.3 SDK, and Xcode 3.2.6.

one way to reduce the redundancy is called a convenience constructor. a partial implementation is illustrated below:
#interface MONRoomsClass : NSObject {
NSInteger roomID;
NSString *name;
NSString *desc;
}
#property (nonatomic, readwrite) NSInteger roomID;
#property (nonatomic, copy) NSString *name;
/* note: ivar would normally be named 'description' */
#property (nonatomic, copy) NSString *desc;
/* designated initializer */
- (id)initWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc;
/* convenience constructor */
+ (MONRoomsClass *)newRoomsClassWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc;
/* convenience constructor */
+ (MONRoomsClass *)roomsClassWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc;
#end
#implementation MONRoomsClass
- (id)initWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc
{
/* error checking omitted */
self = [super init];
if (0 != self) {
roomID = inRoomID;
name = [inName copy];
desc = [inDesc copy];
}
return self;
}
+ (MONRoomsClass *)newRoomsClassWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc
{
return [[self alloc] initWithRoomID:inRoomID name:[inName desc:inDesc];
}
+ (MONRoomsClass *)roomsClassWithRoomID:(NSInteger)inRoomID
name:(NSString *)inName
desc:(NSString *)inDesc
{
return [[[self alloc] initWithRoomID:inRoomID
name:inName
desc:inDesc] autorelease];
}
#end
void in_use() {
/* ... */
MONRoomsClass * roomsClass =
[MONRoomsClass newRoomsClassWithRoomID:210
name:#"MH210"
desc:#"Lab"];
[roomsArray addObject:roomsClass];
/* or */
[roomsArray addObject:
[[MONRoomsClass newRoomsClassWithRoomID:210
name:#"MH210"
desc:#"Lab"]
autorelease]];
/* or */
[roomsArray addObject:
[MONRoomsClass roomsClassWithRoomID:210
name:#"MH210"
desc:#"Lab"]];
/* ... */
}

There are a few possibilities for rewriting your array initialisation code. One that comes to mind is:
NSInteger roomIDs[] = { 202, 207, 208, 209, 210, 211 };
NSString *roomNames[] = { #"MH202", #"MH207", #"MH208", #"MH209", #"MH210", #"MH211" };
NSString *roomDescs[] = { #"Office", #"Lab", #"Office", #"Lab", #"Lab", #"Office" };
NSUInteger numberOfRooms = sizeof(roomIDs) / sizeof(NSInteger);
self.roomsArray = [NSMutableArray arrayWithCapacity:numberOfRooms];
for (int i = 0; i < numberOfRooms; i++) {
roomsClass *room = [[[roomsClass alloc] init] autorelease];
room.roomID = roomIDs[i];
room.name = roomNames[i];
room.desc = roomDescs[i];
[self.roomsArray addObject:room];
}
or
typedef struct {
NSInteger roomId;
NSString *name;
NSString *desc;
} RoomData;
RoomData rooms[] = {
{ 202, #"MH202", #"Office" },
{ 207, #"MH207", #"Lab" },
{ 208, #"MH208", #"Office" },
{ 209, #"MH209", #"Lab" },
{ 210, #"MH210", #"Lab" },
{ 211, #"MH211", #"Office" }
};
NSUInteger numberOfRooms = sizeof(rooms) / sizeof(RoomData);
self.roomsArray = [NSMutableArray arrayWithCapacity:numberOfRooms];
for (int i = 0; i < numberOfRooms; i++) {
roomsClass *room = [[[roomsClass alloc] init] autorelease];
room.roomID = rooms[i].roomId;
room.name = rooms[i].name;
room.desc = rooms[i].desc;
[self.roomsArray addObject:room];
}
If you couple those with #Justin’s convenience constructor, the for loop can be simplified to:
for (int i = 0; i < numberOfRooms; i++) {
[self.roomsArray addObject:[roomsClassWithRoomID:roomIDS[i]
name:roomNames[i]
desc:roomDescs[i]]];
}
or
for (int i = 0; i < numberOfRooms; i++) {
[self.roomsArray addObject:[roomsClassWithRoomID:rooms[i].roomId
name:rooms[i].name
desc:rooms[i].desc]];
}

Related

Populating UITableView dynamically

I have the following code to fetch the data from URL, store it in arrays, and display it inside the table.
Now the issue is my URL which is feeding data to the tables changes according to the button click i.e. If user clicks button [gainer], data gets fetched from URL related to gainer and so on.
As I have called gainer method in didLoad method, initially data is displayed from the respective URL.But on button click no action is taken. The reason is I'm populating the arrays in methods (gainer and looser) but table is fetching data from the arrays at the time of table creation(and arrays are empty at that point).
I have created button in design view while I'm creating table programmatically.
fetchdataViewController.h
#import <UIKit/UIKit.h>
#interface fetchdataViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
IBOutlet UIWebView *webView;
NSMutableArray *arr1;
NSMutableArray *atarr;
NSMutableArray *arr2;
NSMutableArray *a;
NSMutableArray *b;
NSMutableArray *c;
NSMutableArray *d;
UITableView *aTableView;
}
-(IBAction)btnClicked:(id)sender;
-(IBAction)btnClicked1:(id)sender;
-(void)gainer;
-(void)looser;
#property(nonatomic,retain)NSMutableArray *arr1;
#property(nonatomic,retain)NSMutableArray *arr2;
#property(nonatomic,retain)NSMutableArray *atarr;
#property(nonatomic,retain)NSMutableArray *a;
#property(nonatomic,retain)NSMutableArray *b;
#property(nonatomic,retain)NSMutableArray *c;
#property(nonatomic,retain)NSMutableArray *d;
#property(nonatomic,retain)UIWebView *webView;
#property(nonatomic,retain)UITableView *aTableView;
#end
fetchdataViewController.m
#import "fetchdataViewController.h"
#implementation fetchdataViewController
NSMutableArray *atarr;
NSMutableArray *arr1;
NSMutableArray *arr2;
NSMutableArray *a;
NSMutableArray *b;
NSMutableArray *c;
NSMutableArray *d;
NSMutableString *mainstr;
NSMutableString *str;
#synthesize webView;
#synthesize arr1;
#synthesize arr2;
#synthesize atarr;
#synthesize a;
#synthesize b;
#synthesize c;
#synthesize d;
#synthesize aTableView;
int i,j;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [a count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier=#"Cell";
static NSInteger StateTag = 1;
static NSInteger CapitalTag = 2;
static NSInteger StateTag1 = 3;
static NSInteger StateTag2 = 4;
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell=[[[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]autorelease];
CGRect frame;
frame.origin.x = 10;
frame.origin.y = 5;
frame.size.height = 35;
frame.size.width = 170;
UILabel *capitalLabel = [[UILabel alloc] initWithFrame:frame];
capitalLabel.tag = CapitalTag;
[cell.contentView addSubview:capitalLabel];
frame.origin.x += 125;
UILabel *stateLabel = [[UILabel alloc] initWithFrame:frame];
stateLabel.tag = StateTag;
[cell.contentView addSubview:stateLabel];
frame.origin.x += 100;
UILabel *stateLabel1 = [[UILabel alloc] initWithFrame:frame];
stateLabel1.tag = StateTag1;
[cell.contentView addSubview:stateLabel1];
frame.origin.x += 100;
UILabel *stateLabel2 = [[UILabel alloc] initWithFrame:frame];
stateLabel2.tag = StateTag2;
[cell.contentView addSubview:stateLabel2];
}
UILabel *capitalLabel = (UILabel *) [cell.contentView viewWithTag:CapitalTag];
UILabel *stateLabel = (UILabel *) [cell.contentView viewWithTag:StateTag];
UILabel *stateLabel1 = (UILabel *) [cell.contentView viewWithTag:StateTag1];
UILabel *stateLabel2 = (UILabel *) [cell.contentView viewWithTag:StateTag2];
capitalLabel.text=[a objectAtIndex:indexPath.row];
stateLabel.text = [b objectAtIndex:indexPath.row];
stateLabel1.text = [c objectAtIndex:indexPath.row];
stateLabel2.text = [d objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)btnClicked:(id)sender{
[self gainer];
}
-(IBAction)btnClicked1:(id)sender {
[self looser];
}
-(void)gainer{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
NSURL *url=[NSURL URLWithString:#"http://ipad.idealake.com/default.aspx?id=G"];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
[webView loadRequest:req];
//storing page data in string
mainstr=[[NSMutableString alloc] initWithContentsOfURL:url];
atarr=[mainstr componentsSeparatedByString:#"#"];
NSString *str2;
NSString *str3;
for(int i=0; i<[atarr count]-1; i++)
{
// NSLog(#"i=:%i",i);
NSMutableString *str = [atarr objectAtIndex:i];
if (str!= nil)
arr1=[str componentsSeparatedByString:#";"];
for (int k=0;k<[arr1 count];k++)
{
str2 = [arr1 objectAtIndex:k];
[arr2 addObject:str2];
}
}
else
{
//NSLog (#"Nill");
}
}
for(int l=0;l<[arr2 count]/4;l++){
str3=[arr2 objectAtIndex:4*l];
[a addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+1];
[b addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+2];
[c addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+3];
[d addObject:str3];
}
}
-(void)looser{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
NSURL *url=[NSURL URLWithString:#"http://ipad.idealake.com/default.aspx?id=L"];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
[webView loadRequest:req];
mainstr=[[NSMutableString alloc] initWithContentsOfURL:url];
atarr=[mainstr componentsSeparatedByString:#"#"];
NSString *str2;
NSString *str3;
for(int i=0; i<[atarr count]-1; i++)
{
NSMutableString *str = [atarr objectAtIndex:i];
if (str!= nil)
{
arr1=[str componentsSeparatedByString:#";"];
for (int k=0;k<[arr1 count];k++)
{
str2 = [arr1 objectAtIndex:k];
[arr2 addObject:str2];
}
}
else
{
//NSLog (#"Nill");
}
}
for(int l=0;l<[arr2 count]/4;l++){
str3=[arr2 objectAtIndex:4*l];
[a addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+1];
[b addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+2];
[c addObject:str3];
str3=[arr2 objectAtIndex:(4*l)+3];
[d addObject:str3];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
arr1=[[NSMutableArray alloc]init];
arr2=[[NSMutableArray alloc]init];
a=[[NSMutableArray alloc]init];
b=[[NSMutableArray alloc]init];
c=[[NSMutableArray alloc]init];
d=[[NSMutableArray alloc]init];
[self gainer];
[super viewDidLoad];
aTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame] style:UITableViewStyleGrouped];
aTableView.dataSource = self;
aTableView.delegate = self;
aTableView.frame = CGRectMake(0, 10, 720, 500);
[self.view addSubview:aTableView];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
UPDATE
When I run the below code, I get this output. That shaded grey portion is my main concern.
THANKS IN ADVANCE
You need to tell your UITableView that the data has changed by calling reloadData.
Use [self.tableview reloadData] after each change of url and with new arrays filled.

Three20 to save images?(Close)

i'm a new iPhone application developer,i need create one application like photo gallery.Now my problem is i donno how to save a image to photo album.
i have build my project is no error no werning to me.in my simulator can run the project.
But i cnt see any things i add.Hope can help me.Thanks.
my code here.
Three20PhotoDemoAppDelegate.h
#import <UIKit/UIKit.h>
#interface Three20PhotoDemoAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
Three20PhotoDemoAppDelegate.m
#import "Three20PhotoDemoAppDelegate.h"
#import "AlbumController.h"
#import <Three20/Three20.h>
#implementation Three20PhotoDemoAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch
TTNavigator* navigator = [TTNavigator navigator];
TTURLMap* map = navigator.URLMap;
[map from:#"demo://album" toViewController: [AlbumController class]];
[navigator openURLAction:[TTURLAction actionWithURLPath:#"demo://album"]];
return YES;
}
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)URL {
[[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:URL.absoluteString]];
return YES;
}
- (void)dealloc {
[super dealloc];
}
#end
PhotoSource.h
#import <Three20/Three20.h>
#import <Three20/Three20+Additions.h>
typedef enum {
PhotoSourceNormal = 0,
PhotoSourceDelayed = 1,
PhotoSourceVariableCount = 2,
PhotoSourceLoadError = 4,
} PhotoSourceType;
#interface PhotoSource : TTURLRequestModel <TTPhotoSource> {
PhotoSourceType _type;
NSString* _title;
NSMutableArray* _photos;
NSArray* _tempPhotos;
NSTimer* _fakeLoadTimer;
}
- (id)initWithType:(PhotoSourceType)type title:(NSString*)title
photos:(NSArray*)photos photos2:(NSArray*)photos2;
#end
PhotoSource.m
import "PhotoSource.h"
#implementation PhotoSource
#synthesize title = _title;
- (void)fakeLoadReady {
_fakeLoadTimer = nil;
if (_type & PhotoSourceLoadError) {
[_delegates makeObjectsPerformSelector: #selector(model:didFailLoadWithError:)
withObject: self
withObject: nil];
} else {
NSMutableArray* newPhotos = [NSMutableArray array];
for (int i = 0; i < _photos.count; ++i) {
id<TTPhoto> photo = [_photos objectAtIndex:i];
if ((NSNull*)photo != [NSNull null]) {
[newPhotos addObject:photo];
}
}
[newPhotos addObjectsFromArray:_tempPhotos];
TT_RELEASE_SAFELY(_tempPhotos);
[_photos release];
_photos = [newPhotos retain];
for (int i = 0; i < _photos.count; ++i) {
id<TTPhoto> photo = [_photos objectAtIndex:i];
if ((NSNull*)photo != [NSNull null]) {
photo.photoSource = self;
photo.index = i;
}
}
[_delegates makeObjectsPerformSelector:#selector(modelDidFinishLoad:) withObject:self];
}
}
- (id)initWithType:(PhotoSourceType)type title:(NSString*)title photos:(NSArray*)photos
photos2:(NSArray*)photos2 {
if (self = [super init]) {
_type = type;
_title = [title copy];
_photos = photos2 ? [photos mutableCopy] : [[NSMutableArray alloc] init];
_tempPhotos = photos2 ? [photos2 retain] : [photos retain];
_fakeLoadTimer = nil;
for (int i = 0; i < _photos.count; ++i) {
id<TTPhoto> photo = [_photos objectAtIndex:i];
if ((NSNull*)photo != [NSNull null]) {
photo.photoSource = self;
photo.index = i;
}
}
if (!(_type & PhotoSourceDelayed || photos2)) {
[self performSelector:#selector(fakeLoadReady)];
}
}
return self;
}
- (id)init {
return [self initWithType:PhotoSourceNormal title:nil photos:nil photos2:nil];
}
- (void)dealloc {
[_fakeLoadTimer invalidate];
TT_RELEASE_SAFELY(_photos);
TT_RELEASE_SAFELY(_tempPhotos);
TT_RELEASE_SAFELY(_title);
[super dealloc];
}
- (BOOL)isLoading {
return !!_fakeLoadTimer;
}
- (BOOL)isLoaded {
return !!_photos;
}
- (void)load:(TTURLRequestCachePolicy)cachePolicy more:(BOOL)more {
if (cachePolicy & TTURLRequestCachePolicyNetwork) {
[_delegates makeObjectsPerformSelector:#selector(modelDidStartLoad:) withObject:self];
TT_RELEASE_SAFELY(_photos);
_fakeLoadTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(fakeLoadReady) userInfo:nil repeats:NO];
}
}
- (void)cancel {
[_fakeLoadTimer invalidate];
_fakeLoadTimer = nil;
}
- (NSInteger)numberOfPhotos {
if (_tempPhotos) {
return _photos.count + (_type & PhotoSourceVariableCount ? 0 : _tempPhotos.count);
} else {
return _photos.count;
}
}
- (NSInteger)maxPhotoIndex {
return _photos.count-1;
}
- (id<TTPhoto>)photoAtIndex:(NSInteger)photoIndex {
if (photoIndex < _photos.count) {
id photo = [_photos objectAtIndex:photoIndex];
if (photo == [NSNull null]) {
return nil;
} else {
return photo;
}
} else {
return nil;
}
}
#end
Photo.h
#import <Three20/Three20.h>
#interface Photo : NSObject <TTPhoto> {
id<TTPhotoSource> _photoSource;
NSString* _thumbURL;
NSString* _smallURL;
NSString* _URL;
CGSize _size;
NSInteger _index;
NSString* _caption;
}
- (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size;
- (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size
caption:(NSString*)caption;
#end
Photo.m
#import "Photo.h"
#implementation Photo
#synthesize photoSource = _photoSource, size = _size, index = _index, caption = _caption;
- (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size {
return [self initWithURL:URL smallURL:smallURL size:size caption:nil];
}
- (id)initWithURL:(NSString*)URL smallURL:(NSString*)smallURL size:(CGSize)size
caption:(NSString*)caption {
if (self = [super init]) {
_photoSource = nil;
_URL = [URL copy];
_smallURL = [smallURL copy];
_thumbURL = [smallURL copy];
_size = size;
_caption;
_index = NSIntegerMax;
}
return self;
}
- (void)dealloc {
TT_RELEASE_SAFELY(_URL);
TT_RELEASE_SAFELY(_smallURL);
TT_RELEASE_SAFELY(_thumbURL);
TT_RELEASE_SAFELY(_caption);
[super dealloc];
}
- (void)viewDidLoad {
}
- (NSString*)URLForVersion:(TTPhotoVersion)version {
if (version == TTPhotoVersionLarge) {
return _URL;
} else if (version == TTPhotoVersionMedium) {
return _URL;
} else if (version == TTPhotoVersionSmall) {
return _smallURL;
} else if (version == TTPhotoVersionThumbnail) {
return _thumbURL;
} else {
return nil;
}
}
#end
AlbumController.h
#import <Three20/Three20.h>
#interface AlbumController : TTPhotoViewController <UIActionSheetDelegate>{
NSArray *images;
UIBarButtonItem *_clickActionItem;
UIToolbar *_toolbar;
}
#property (nonatomic, retain) NSArray *images;
#property (nonatomic, retain) UIBarButtonItem *_clickActionItem;
#property (nonatomic, retain) UIToolbar *_toolbar;
#end
AlbumController.m
#import "AlbumController.h"
#import "PhotoSource.h"
#import "Photo.h"
#implementation AlbumController
#synthesize images;
- (void)loadView {
CGRect screenFrame = [UIScreen mainScreen].bounds;
self.view = [[[UIView alloc] initWithFrame:screenFrame]
autorelease];
CGRect innerFrame = CGRectMake(0, 0,
screenFrame.size.width,
screenFrame.size.height);
_innerView = [[UIView alloc] initWithFrame:innerFrame];
_innerView.autoresizingMask = UIViewAutoresizingFlexibleWidth|
UIViewAutoresizingFlexibleHeight;
[self.view addSubview:_innerView];
_scrollView = [[TTScrollView alloc] initWithFrame:screenFrame];
_scrollView.delegate = self;
_scrollView.dataSource = self;
_scrollView.backgroundColor = [UIColor blackColor];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth|
UIViewAutoresizingFlexibleHeight;
[_innerView addSubview:_scrollView];
UIBarButtonItem *_actionButton = [[UIBarButtonItem alloc] initWithImage:
TTIMAGE(#"bundle://Three20.bundle/images/imageAction.png")
style:UIBarButtonItemStylePlain target:self action:#selector
(popupActionSheet)];
_nextButton = [[UIBarButtonItem alloc] initWithImage:
TTIMAGE(#"bundle://Three20.bundle/images/nextIcon.png")
style:UIBarButtonItemStylePlain target:self action:#selector
(nextAction)];
_previousButton = [[UIBarButtonItem alloc] initWithImage:
TTIMAGE(#"bundle://Three20.bundle/images/previousIcon.png")
style:UIBarButtonItemStylePlain target:self action:#selector
(previousAction)];
UIBarButtonItem* playButton = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:
UIBarButtonSystemItemPlay target:self action:#selector
(playAction)] autorelease];
playButton.tag = 1;
UIBarItem* space = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:
UIBarButtonSystemItemFlexibleSpace target:nil action:nil]
autorelease];
_toolbar = [[UIToolbar alloc] initWithFrame:
CGRectMake(0, screenFrame.size.height - TT_ROW_HEIGHT,
screenFrame.size.width, TT_ROW_HEIGHT)];
_toolbar.barStyle = self.navigationBarStyle;
_toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth|
UIViewAutoresizingFlexibleTopMargin;
_toolbar.items = [NSArray arrayWithObjects:
_actionButton, space, _previousButton, space,
_nextButton, space, nil];
[_innerView addSubview:_toolbar];
}
//(Just to add an action sheet)
//At the bottom of that codefile -- I added:
-(void)popupActionSheet {
UIActionSheet *popupQuery = [[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Save Image",nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQuery showInView:self.view];
[popupQuery release];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:
(int)buttonIndex {
//UIImage* image = [[TTURLCache sharedCache] imageForURL:imageURL];
if (buttonIndex==0){
UIImage* thisImage = [[TTURLCache sharedCache] imageForURL:
[_centerPhoto URLForVersion:TTPhotoVersionLarge]];
UIImageWriteToSavedPhotosAlbum(thisImage, nil, nil, nil);
//{UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"URL"
//message:[_centerPhoto URLForVersion:TTPhotoVersionLarge] delegate:self cancelButtonTitle:#"No" ,otherButtonTitles:#"Yes", nil];
//[alert show];}
}
}
-(void)createPhotos {
images = [[NSArray alloc] initWithObjects:
[[[Photo alloc] initWithURL:#"bundle://14.png" smallURL:#"bundle://14.png"
size:CGSizeMake(320, 212)] autorelease],
[[[Photo alloc] initWithURL:#"bundle://30.png" smallURL:#"bundle://30.png"
size:CGSizeMake(320, 212)] autorelease],
[[[Photo alloc] initWithURL:#"bundle://back.jpeg" smallURL:#"bundle://back.jpeg"
size:CGSizeMake(319, 317)] autorelease],
nil];
}
- (void)viewDidLoad {
//[self loadView];
[self createPhotos]; // method to set up the photos array
self.photoSource = [[PhotoSource alloc]
initWithType:PhotoSourceNormal
title:#"SexyGirl"
photos:images
photos2:nil
];
}
#end
If all you need is to save an image to the Photos album, you can use:
UIImage *myImage;
UIImageWriteToSavedPhotosAlbum(myImage,nil,nil,nil);
If this is not your problem, then I don't get it. If you don't tell us where the problem is, posting three pages worth of code is pretty useless.

why is the NSMutableArray is being destroyed in this loop?

It is the arrayOfPerformances that is getting broken.
here is the .h for the array:
NSMutableArray * arrayOfPerformances;
}
#property (nonatomic, retain) NSMutableArray * arrayOfPerformances;
and the .m that has the loop:
[dataArray release];
[dataDictionary release];
dataArray = [[NSMutableArray alloc] init];
dataDictionary = [[NSMutableDictionary alloc] init];
NSDate * CurrentDate = start;
int i = 0;
NSMutableArray * arrayOfPerformancesForCurrentDate = [[NSMutableArray alloc] init];
while(YES)
{
i = 0;
if ([arrayOfPerformancesForCurrentDate count] > 0)
{
[arrayOfPerformancesForCurrentDate removeAllObjects];
}
for (i; i < self.arrayOfPerformances.count; i++)
{
Performance * performanceItem = [[Performance alloc] init];
performanceItem = [self.arrayOfPerformances objectAtIndex:i];
NSString * sPerformanceDate = [performanceItem.sDate substringToIndex:10];
NSString * sCurrentDate = [CurrentDate dateDescription];
if([sPerformanceDate isEqualToString:sCurrentDate])
{
[arrayOfPerformancesForCurrentDate addObject:performanceItem];
}
[performanceItem release];
}
if ([arrayOfPerformancesForCurrentDate count] >= 1)
{
[dataDictionary setObject:arrayOfPerformancesForCurrentDate forKey:CurrentDate];
[dataArray addObject:[NSNumber numberWithBool:YES]];
}
else
{
[dataArray addObject:[NSNumber numberWithBool:NO]];
}
TKDateInformation info = [CurrentDate dateInformation];
info.day++;
CurrentDate = [NSDate dateFromDateInformation:info];
if([CurrentDate compare:end]==NSOrderedDescending) break;
}
Any help would be appreciated. I dont understand why this is happening?
This part doesn't look right:
Performance * performanceItem = [[Performance alloc] init]; <--
performanceItem = [self.arrayOfPerformances objectAtIndex:i]; <--
NSString * sPerformanceDate = [performanceItem.sDate substringToIndex:10];
NSString * sCurrentDate = [CurrentDate dateDescription];
if([sPerformanceDate isEqualToString:sCurrentDate])
{
[arrayOfPerformancesForCurrentDate addObject:performanceItem];
}
[performanceItem release]; <--
You alloc+init performanceItem but then set it to an object in arrayOfPerformances and then you release it (while it's pointing to the object in arrayOfPerformances).
Change that section to this:
Performance *performanceItem = [self.arrayOfPerformances objectAtIndex:i];
NSString * sPerformanceDate = [performanceItem.sDate substringToIndex:10];
NSString * sCurrentDate = [CurrentDate dateDescription];
if([sPerformanceDate isEqualToString:sCurrentDate])
{
[arrayOfPerformancesForCurrentDate addObject:performanceItem];
}
//don't release performanceItem
I don't think arrayOfPerformances of being destroyed. It appears you aren't even initializing it anywhere.

NSCoding with as NSString inside a object

My issue is then I retrieve my NSArray of Store objects, all my NSString properties are causing BadAccess errors. The int and double properties work fine!
store.h
#interface Store : NSObject<NSCoding> {
NSString *Name;
NSString *Address;
NSString *Phone;
double GeoLong;
double GeoLat;
int ID;
}
#property (nonatomic, retain) NSString *Name;
#property (nonatomic, retain) NSString *Address;
#property (nonatomic, retain) NSString *Phone;
#property (nonatomic) double GeoLat;
#property (nonatomic) double GeoLong;
#property (nonatomic) int ID;
#end
store.m
#implementation Store
#synthesize Name;
#synthesize ID;
#synthesize Address;
#synthesize Phone;
#synthesize GeoLat;
#synthesize GeoLong;
/** Implentation of the NSCoding protocol. */
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeInt:ID forKey:#"ID"];
[encoder encodeDouble:GeoLat forKey:#"GeoLat"];
[encoder encodeDouble:GeoLong forKey:#"GeoLong"];
NSLog(#"Name in encode: %#", Name); //WORKS!
[encoder encodeObject:Name forKey:#"Name"];
[encoder encodeObject:Phone forKey:#"Phone"];
[encoder encodeObject:Address forKey:#"Address"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
// Init first.
if(self = [self init]){
ID = [decoder decodeIntForKey:#"ID"];
GeoLat = [decoder decodeDoubleForKey:#"GeoLat"];
GeoLong = [decoder decodeDoubleForKey:#"GeoLong"];
Name = [decoder decodeObjectForKey:#"Name"];
NSLog(#"Name in decode: %#", Name); //WORKS! logs the name
Address = [decoder decodeObjectForKey:#"Address"];
Phone = [decoder decodeObjectForKey:#"Phone"];
}
return self;
}
- (void)dealloc
{
[Name release];
[ID release];
[Address release];
[Phone release];
[super dealloc];
}
#end
Here is my code for storing and retriving the array.
//streams contains the data i will populate my array with.
for (ndx = 0; ndx < streams.count; ndx++) {
NSDictionary *stream = (NSDictionary *)[streams objectAtIndex:ndx];
Store *item = [[Store alloc] init] ;
item.Name = [stream valueForKey:#"Name"];
item.Address = [stream valueForKey:#"Address"];
item.Phone = [stream valueForKey:#"Phone"];
item.GeoLat = [[stream valueForKey:#"GeoLat"] doubleValue];
item.GeoLong = [[stream valueForKey:#"GeoLong"] doubleValue];
item.ID = [[stream valueForKey:#"ID"] intValue];
[listToReturn addObject:item];
}
}
//test to check if it works
for(int i = 0; i < [listToReturn count]; i++){
Store *item = (Store *)[listToReturn objectAtIndex:i];
NSLog(#"Name: %#", item.Name); //works
}
//save
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:listToReturn] forKey:#"stores"];
// retrieve
NSMutableArray *stores = [NSMutableArray new];
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:#"stores"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
stores = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
stores = [[NSMutableArray alloc] init];
}
if ([stores count] > 0) {
NSMutableArray * annotations = [[NSMutableArray alloc] init];
for(int i = 0;i< [stores count]; i++){
Store *store = [stores objectAtIndex: i];
CLLocationCoordinate2D location;
if(store.GeoLat != 0 && store.GeoLong != 0){
location.latitude = store.GeoLat;
location.longitude = store.GeoLong; //works
NSLog(#"Adding store: %#", store.Name); //DONT WORK!! <-- MAIN PROBLEM
}
}
}
Feels like I tried everything but can't figure out how it works in the decode but not when in loop the array after I put it into a array.
Anyone have any ideas?
You're not retaining the properties in initWithCoder.
Name = [decoder decodeObjectForKey:#"Name"];
is not using the setter of the (retaining) property you've defined. You're just setting the ivar. That means you don't acquire ownership and it can be deallocated.
Here are two ways you can retain the properties in your case:
self.Name = [decoder decodeObjectForKey:#"Name"];
Name = [[decoder decodeObjectForKey:#"Name"] retain];

Memory leaks in NSMutableDictionary

My coding contains a memory leak, and somehow I can't find the leak.
Leaks points me in the direction of the way I create "ReportDetailItems"
e.g. areaContainer = [[[ReportDetailItem alloc] init] autorelease];
I've been looking at this for hours and I am at a total loss, the objects reported leaking are "ReportDetailItem", and the NSMutableDictionary contained in those objects.
Please advice.
------[ReportDetailItem.h
#interface ReportDetailItem : NSObject
{
NSNumber *total;
NSMutableDictionary *items;
}
#property (nonatomic, retain) NSNumber *total;
#property (nonatomic, retain) NSMutableDictionary *items;
- (NSString *)description;
#end
------[ReportDetailItem.m
#synthesize items, total;
- (id)init {
if (self = [super init]) {
self.items = [NSMutableDictionary dictionaryWithCapacity:0];
DLog("Alloc: %d", [items retainCount]);
}
return self;
}
- (NSString *)description {
return #"ReportDetailItem";
}
- (void)release {
[super release];
}
- (void)dealloc {
[self.items release];
[self.total release];
items = nil;
total = nil;
[super dealloc];
}
#end
------[Leaking code
NSError *error;
NSArray *data = [self.managedObjectContext executeFetchRequest:request error:&error];
if (data == nil || [data count] == 0) {
DLog(#"No data.")
} else {
for (int i=0; i < [data count]; i++) {
TaskEntity *task = [data objectAtIndex:i];
NSString *areaKey = task.activity.project.area.title.text;
NSString *projectKey = task.activity.project.title.text;
NSString *activityKey = task.activity.title.text;
ReportDetailItem *areaContainer;
if (![dataSource objectForKey:areaKey]) {
areaContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
areaContainer = [dataSource objectForKey:areaKey];
}
areaContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [areaContainer.total intValue])];
[dataSource setObject:areaContainer forKey:areaKey];
ReportDetailItem *projectContainer;
if (![areaContainer.items objectForKey:projectKey]) {
projectContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
projectContainer = [areaContainer.items objectForKey:projectKey];
}
projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
[areaContainer.items setObject:projectContainer forKey:projectKey];
ReportDetailItem *activityContainer;
if (![projectContainer.items objectForKey:activityKey]) {
activityContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
activityContainer = [projectContainer.items objectForKey:activityKey];
}
activityContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [activityContainer.total intValue])];
[projectContainer.items setObject:activityContainer forKey:activityKey];
}
}
I found it, the leak was located in the way I allocated the "dataSource"
---[Leak
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = [[NSMutableDictionary alloc] init];
[self fetchData];
}
---[No leak
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
self.dataSource = dict;
[dict release];
[self fetchData];
}
I'm pretty skeptic about the two ways u assign pointers to the ReportDetailItem. Why are you trying to autorelease the object in the first place? If not try this
ReportDetailItem *projectContainer;
if (![areaContainer.items objectForKey:projectKey]) {
projectContainer = [[ReportDetailItem alloc] init];
} else {
projectContainer = [[areaContainer.items objectForKey:projectKey] retain];
}
projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
[areaContainer.items setObject:projectContainer forKey:projectKey];
if(projectContainer) {
[projectContainer release];
projectContainer = nil;
}