I have an existing iphone project with a UITabBar. Now I need styled text and in-text links to other ViewControllers in my app. I am trying to integrate TTStyledTextLabel.
I have a FirstViewController:UITabelViewController with this tableView:didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *url;
if ([self.filteredQuestions count]>0) {
url = [NSString stringWithFormat:#"%#%d", #"tt://question/", [[self.filteredQuestions objectAtIndex:indexPath.row] id]];
[[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath: url] applyAnimated:YES]];
} else {
Question * q = [self.questions objectAtIndex:indexPath.row] ;
url = [NSString stringWithFormat:#"%#%d", #"tt://question/", [q.id intValue]];
}
TTDPRINT(#"%#", url);
TTNavigator *navigator = [TTNavigator navigator];
[navigator openURLAction:[[TTURLAction actionWithURLPath: url] applyAnimated:YES]];
}
My mapping looks like this:
TTNavigator* navigator = [TTNavigator navigator];
navigator.window = window;
navigator.supportsShakeToReload = YES;
TTURLMap* map = navigator.URLMap;
[map from:#"*" toViewController:[TTWebController class]];
[map from:#"tt://question/(initWithQID:)" toViewController:[QuestionDetailViewController class]];
and my QuestionDetailViewController:
#interface QuestionDetailViewController : UIViewController <UIScrollViewDelegate , QuestionDetailViewProtocol> {
Question *question;
}
#property(nonatomic,retain) Question *question;
-(id) initWithQID:(NSString *)qid;
-(void) goBack:(id)sender;
#end
When I hit a cell, q QuestionDetailViewController will be called — but the navigationBar wont
#implementation QuestionDetailViewController
#synthesize question;
-(id) initWithQID:(NSString *)qid
{
if (self = [super initWithNibName:#"QuestionDetailViewController" bundle:nil]) {
//;
TTDPRINT(#"%#", qid);
NSManagedObjectContext *managedObjectContext = [(domainAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"id == %#", qid];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Question"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
if (error==nil && [array count]>0 ) {
self.question = [array objectAtIndex:0];
} else {
TTDPRINT(#"error: %#", array);
}
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[TTStyleSheet setGlobalStyleSheet:[[[TextTestStyleSheet alloc] init] autorelease]];
[self.navigationController.navigationBar setTranslucent:YES];
NSArray *includedLinks = [self.question.answer.text vs_extractExternalLinks];
NSMutableDictionary *linksToTT = [[NSMutableDictionary alloc] init];
for (NSArray *a in includedLinks) {
NSString *s = [a objectAtIndex:3];
if ([s hasPrefix:#"/answer/"] || [s hasPrefix:#"http://domain.com/answer/"] || [s hasPrefix:#"http://www.domain.com/answer/"]) {
NSString *ttAdress = #"tt://question/";
NSArray *adressComps = [s pathComponents];
for (NSString *s in adressComps) {
if ([s isEqualToString:#"qid"]) {
ttAdress = [ttAdress stringByAppendingString:[adressComps objectAtIndex:[adressComps indexOfObject:s]+1]];
}
}
[linksToTT setObject:ttAdress forKey:s];
}
}
for (NSString *k in [linksToTT allKeys]) {
self.question.answer.text = [self.question.answer.text stringByReplacingOccurrencesOfString:k withString: [linksToTT objectForKey:k]];
}
TTStyledTextLabel *answerText = [[[TTStyledTextLabel alloc] initWithFrame:CGRectMake(0, 0, 320, 700)] autorelease];
if (![[self.question.answer.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] hasPrefix:#"<div"]) {
self.question.answer.text = [NSString stringWithFormat:#"%<div>%#</div>", self.question.answer.text];
}
NSString * s = [NSString stringWithFormat:#"<div class=\"header\">%#</div>\n%#",self.question.title ,self.question.answer.text];
answerText.text = [TTStyledText textFromXHTML:s lineBreaks:YES URLs:YES];
answerText.contentInset = UIEdgeInsetsMake(20, 15, 20, 15);
[answerText sizeToFit];
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.view addSubview:answerText];
[(UIScrollView *)self.view setContentSize:answerText.frame.size];
self.view.backgroundColor = [UIColor whiteColor];
[linksToTT release];
}
.......
#end
This works quite nice, as soon as a cell is touched, a QuestionDetailViewController is called and pushed — but the tabBar will disappear, and the navigationItem — I set it like this: self.navigationItem.title =#"back to first screen"; — won't be shown. And it just appears without animation.
But if I press a link inside the TTStyledTextLabel the animation works, the navigationItem will be shown.
How can I make the animation, the navigationItem and the tabBar be shown?
I found a solution:
My QuestionDetailViewController implements the TTNavigatorDelegate.
-(BOOL)navigator:(TTNavigator *)navigator shouldOpenURL:(NSURL *)URL will always return NO, but will call [self.navigationController pushViewController:c animated:YES];
-(BOOL)navigator:(TTNavigator *)navigator shouldOpenURL:(NSURL *)URL {
NSEntityDescription *entity;
NSPredicate *predicate;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
if ([[URL host] isEqualToString:#"question"]) {
entity =[NSEntityDescription entityForName:#"Question" inManagedObjectContext:managedObjectContext];
predicate = [NSPredicate predicateWithFormat:#"id == %#", [[URL path] stringByReplacingOccurrencesOfString:#"/" withString:#""]];
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error =nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
if (error==nil && [array count] >0) {
QuestionDetailViewController *c = [[[QuestionDetailViewController alloc] init] autorelease];
c.question = [array objectAtIndex:0];
[self.navigationController pushViewController:c animated:YES];
}
}
[request release];
return NO;
}
In your TableViewController, add:
- (id<UITableViewDelegate>)createDelegate {
return self;
}
Then you can implement your own didSelectRowAtIndexPath and accessoryButtonTappedForRowWithIndexPath methods.
Related
In a view I am showing images which I am fetching from coredata, The images I am showing using carousel classes. In the same view I have facebook button which will navigate me to another screen. When I am clicking the Facebook button then the action is not getting performed, after the images are loaded only the next screen is coming, the button action is not getting called as soon as I click on it.
In viewDidLoad I have called:
[self performSelectorInBackground:#selector(popularImages) withObject:nil];
The popularImages method:
- (void)popularImages
{
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Deals"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ispopular == 1"];
[request setPredicate:predicate];
NSLog(#"popular Hypes called");
[self.managedObjectContext executeFetchRequest:request returnManagedObjectIDs:NO onSuccess:^(NSArray *deals) {
deals123 = [[NSMutableArray alloc] initWithArray:deals];
ij = 1;
for (Deals *deals in deals123) {
customizedMessage = [deals valueForKeyPath:#"txtmsgrec"];
dealIdString = [deals valueForKeyPath:#"dealsId"];
descriptionStr = [deals valueForKeyPath:#"dealdescription"];
captionStrArray = [deals valueForKeyPath:#"dealsassets.caption"];
[customizedMessageDict setObject:customizedMessage forKey:[NSString stringWithFormat:#"dealid%d",ij]];
[dealDict setObject:customizedMessageDict forKey:#"dealsmessage"];
[dealsIdDict setObject:dealIdString forKey:[NSString stringWithFormat:#"dealid%d",ij]];
[dealDict setObject:dealsIdDict forKey:#"dealsId"];
NSDictionary *dict = [NSDictionary dictionaryWithObject:captionStrArray forKey:#"caption"];
NSArray *captionTemparr = [[dict objectForKey:#"caption"] allObjects];
NSArray *assets = [deals valueForKeyPath:#"dealsassets.dealassetid"];
NSDictionary *dealassetidDict = [NSDictionary dictionaryWithObject:assets forKey:#"dealassetid"];
NSArray *dealassetidTemparr = [[dealassetidDict objectForKey:#"dealassetid"] allObjects];
[dealsUrlDict setObject:[[dealassetidDict objectForKey:#"dealassetid"] allObjects] forKey:[NSString stringWithFormat:#"dealid%d",ij]];
[dealDict setObject:dealsUrlDict forKey:#"delasURL"];
[dealsdescriptionDict setObject:descriptionStr forKey:[NSString stringWithFormat:#"dealid%d",ij]];
[dealDict setObject:dealsdescriptionDict forKey:#"dealsDescription"];
[dealscaptionDict setObject:captionTemparr forKey:[NSString stringWithFormat:#"dealid%d",ij]];
[dealDict setObject:dealscaptionDict forKey:#"dealscaption"];
ij++;
}
NSArray *array = [[dealDict valueForKey:#"delasURL"]allKeys];
NSLog(#"allKeys]class %#",[[[dealDict valueForKey:#"delasURL"]allKeys]class]);
NSDictionary *dealurlDict = [dealDict valueForKey:#"delasURL"];
NSDictionary *dealDescDict = [dealDict valueForKey:#"dealsDescription"];
NSDictionary *dealCaptionDict = [dealDict valueForKey:#"dealscaption"];
NSDictionary *dealIDDict = [dealDict valueForKey:#"dealsId"];
NSDictionary *dealMessageDict = [dealDict valueForKey:#"dealsmessage"];
for(int i=0;i<[array count];i++)
{
NSString *keyvalue = (NSString *)[array objectAtIndex:i];
NSString *dealId = [dealIDDict valueForKey:keyvalue];
NSArray *dealUrl = [dealurlDict valueForKey:keyvalue];
NSString *dealdesc = [dealDescDict valueForKey:keyvalue];
NSArray *dealcaption = [dealCaptionDict valueForKey:keyvalue];
NSString *dealMessage = [dealMessageDict valueForKey:keyvalue];
if([dealUrl count] == [dealcaption count])
{
//[dealUrl enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop)
for(int j = 0; j<[dealUrl count]; j++)
{
PopularHypesModal *dobject = [[PopularHypesModal alloc]init];
dobject.dealsID = dealId;
dobject.dealDescription = dealdesc;
dobject.dealcaption = [dealcaption objectAtIndex:j];
dobject.dealsUrl = [dealUrl objectAtIndex:j];
dobject.dealsMessage = dealMessage;
[self.items addObject:dobject];
[dobject release];
}
}
else
{
//[dealUrl enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop)
for(int j=0;j<[dealUrl count];j++)
{
PopularHypesModal *dobject=[[PopularHypesModal alloc]init];
dobject.dealsID = dealId;
dobject.dealDescription = dealdesc;
dobject.dealsMessage = dealMessage;
if([dealcaption count]>0)
{
dobject.dealcaption =[dealcaption objectAtIndex:0];
}
dobject.dealsUrl=[dealUrl objectAtIndex:j];
[self.items addObject:dobject];
[dobject release];
}
// ];
}
}
//];
carousel.dataSource = self;
carousel.delegate = self;
}onFailure:^(NSError *error) {
NSLog(#"Error fetching: %#", error);
popularHypes = YES;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Server Problem" message:#"Sorry, There is some Error with server,Please try after some time" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[alert show];
[alert release];
ij++;
}];//1st
[dealDict retain];
}
The button I have added in xib, How can I overcome this?
Running on a background thread shouldn't give you any issues, unless you try to update a UI element from that same background thread. Be sure to forward any UI-related activities to the main thread. For example:
- (void)viewWillAppear:(BOOL)animated {
[self performSelectorInBackground:#selector(refreshTableView)];
[super viewWillAppear:animated];
}
- (void)refreshTableView {
// YourCode
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
hope it's helpful :)
Please try this NSThread method
[NSThread detachNewThreadSelector:#selector(RunMethodEvenWhenMinimized) toTarget:self withObject:dict];
I am working on ELCAlbumPickerController, i am able to select multiple images and upload, but in addition i want to get the file name and datatype of the file. how can i do that?
I am able to select either image or video , how can i select both image and video and any file at a time?
Please find my code below for your reference.
- (void)viewDidLoad {
UIImage *anImage = [UIImage imageNamed:#"elc-ios-icon.png"];
NSArray *Items = [NSArray arrayWithObjects:
#"A text line",
anImage, nil];
UIActivityViewController *ActivityView =
[[UIActivityViewController alloc]
initWithActivityItems:Items applicationActivities:nil];
[self presentViewController:ActivityView animated:YES completion:nil];
}
- (IBAction)launchController
{
ELCAlbumPickerController *albumController = [[ELCAlbumPickerController alloc] initWithNibName: nil bundle: nil];
ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initWithRootViewController:albumController];
[albumController setParent:elcPicker];
[elcPicker setDelegate:self];
ELCImagePickerDemoAppDelegate *app = (ELCImagePickerDemoAppDelegate *)[[UIApplication sharedApplication] delegate];
if ([app.viewController respondsToSelector:#selector(presentViewController:animated:completion:)]){
[app.viewController presentViewController:elcPicker animated:YES completion:nil];
} else {
[app.viewController presentModalViewController:elcPicker animated:YES];
}
[elcPicker release];
[albumController release];
}
- (IBAction)launchSpecialController
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
self.specialLibrary = library;
[library release];
NSMutableArray *groups = [NSMutableArray array];
[_specialLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
[groups addObject:group];
} else {
// this is the end
[self displayPickerForGroup:[groups objectAtIndex:0]];
}
} failureBlock:^(NSError *error) {
self.chosenImages = nil;
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Album Error: %# - %#", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
NSLog(#"A problem occured %#", [error description]);
// an error here means that the asset groups were inaccessable.`
// Maybe the user or system preferences refused access.
}];
}
- (void)displayPickerForGroup:(ALAssetsGroup *)group
{
ELCAssetTablePicker *tablePicker = [[ELCAssetTablePicker alloc] initWithNibName: nil bundle: nil];
tablePicker.singleSelection = YES;
tablePicker.immediateReturn = YES;
ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initWithRootViewController:tablePicker];
elcPicker.delegate = self;
tablePicker.parent = elcPicker;
// Move me
tablePicker.assetGroup = group;
[tablePicker.assetGroup setAssetsFilter:[ALAssetsFilter allAssets]];
if ([self respondsToSelector:#selector(presentViewController:animated:completion:)]){
[self presentViewController:elcPicker animated:YES completion:nil];
} else {
[self presentModalViewController:elcPicker animated:YES];
}
[tablePicker release];
[elcPicker release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
} else {
return toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
}
}
#pragma mark ELCImagePickerControllerDelegate Methods
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]){
[self dismissViewControllerAnimated:YES completion:nil];
} else {
[self dismissModalViewControllerAnimated:YES];
}
for (UIView *v in [_scrollView subviews]) {
[v removeFromSuperview];
}
CGRect workingFrame = _scrollView.frame;
workingFrame.origin.x = 0;
images = [NSMutableArray arrayWithCapacity:[info count]];
for(NSDictionary *dict in info) {
UIImage *image = [dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[_scrollView addSubview:imageview];
[imageview release];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
}
self.chosenImages = images;
NSLog(#"Images:%#",images);
[_scrollView setPagingEnabled:YES];
[_scrollView setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
for (int i=0; i< images.count; i++) {
NSData *image = UIImageJPEGRepresentation(images[i], 0.1);
NSLog(#"NSDATA:%#",image);
NSMutableString *urlString = [[NSMutableString alloc] initWithFormat:#"name=thefile&&filename=recording"];
[urlString appendFormat:#"%#", image];
NSLog(#"urlstring:%#",urlString);
NSData *postData = [urlString dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSString * namecount=[NSString stringWithFormat:#"fn%i.png",i];
NSString * baseurl =[[NSString alloc]initWithFormat:#"http://199.198.12.555/serviceService.svc/serviceupload?fileName=%#",namecount];
NSURL *url = [NSURL URLWithString:baseurl];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod: #"POST"];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPBody:image];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
[connection start];
}
NSLog(#"%#",images[0]);
NSLog(#"%lu",(unsigned long)images.count);
}
-(IBAction)upload:(id)sender{
}
- (void)elcImagePickerControllerDidCancel:(ELCImagePickerController *)picker
{
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]){
[self dismissViewControllerAnimated:YES completion:nil];
} else {
[self dismissModalViewControllerAnimated:YES];
}
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload
{
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
[_specialLibrary release];
[_scrollView release];
[super dealloc];
}
#end
#implementation APActivityProvider
- (id) activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
{
if ( [activityType isEqualToString:UIActivityTypePostToTwitter] )
return #"This is a #twitter post!";
if ( [activityType isEqualToString:UIActivityTypePostToFacebook] )
return #"This is a facebook post!";
if ( [activityType isEqualToString:UIActivityTypeMessage] )
return #"SMS message text";
if ( [activityType isEqualToString:UIActivityTypeMail] )
return #"Email text here!";
if ( [activityType isEqualToString:#"it.albertopasca.myApp"] )
return #"OpenMyapp custom text";
return nil;
}
- (id) activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController { return #""; }
#end
#implementation APActivityIcon
- (NSString *)activityType { return #"it.albertopasca.myApp"; }
- (NSString *)activityTitle { return #"Open Maps"; }
- (UIImage *) activityImage { return [UIImage imageNamed:#"elc-ios-icon.png"]; }
- (BOOL) canPerformWithActivityItems:(NSArray *)activityItems { return YES; }
- (void) prepareWithActivityItems:(NSArray *)activityItems { }
- (UIViewController *) activityViewController { return nil; }
- (void) performActivity {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"maps://"]];
}
#end
Thanks
You can get the asset URL using the key UIImagePickerControllerReferenceURL which would give the 'name', but that probably won't be very useful as its probably a UUID. The UIImagePickerControllerMediaType key contains the type.
In the below sample code, I am a bit lost as to why I am getting a NZombie on the line:
[Category getInitialDataToDisplay:[self getDBPath]];
I have looked through SO posts and other documentation but am new to objective-c and am spinning my wheels on this.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
//Copy database to the user's phone if needed.
[self copyDatabaseIfNeeded];
// Init the Array
activeCategories = [[NSMutableArray alloc] init];
activeSubjects = [[NSMutableArray alloc] init];
categories = [[NSMutableArray alloc] init];
subjects = [[NSMutableArray alloc] init];
quotes = [[NSMutableArray alloc] init];
quoteMaps = [[NSMutableArray alloc] init];
//Initialize the Category array.
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
self.categories = tempArray;
[tempArray release];
//Once the db is copied, get the initial data to display on the screen.
[Category getInitialDataToDisplay:[self getDBPath]];
//populate active subjects and categories:
activeCategories = [self getActiveCategories];
activeSubjects = [self getActiveSubjects];
// sort data
NSSortDescriptor *categorySorter;
NSSortDescriptor *subjectSorter;
categorySorter = [[NSSortDescriptor alloc]initWithKey:#"category_title" ascending:YES];
subjectSorter = [[NSSortDescriptor alloc]initWithKey:#"title" ascending:YES];
NSArray *sortDescriptorsCat = [NSArray arrayWithObject:categorySorter];
NSArray *sortDescriptorsSub = [NSArray arrayWithObject:subjectSorter];
[self.categories sortUsingDescriptors:sortDescriptorsCat];
[self.subjects sortUsingDescriptors:sortDescriptorsSub];
[categorySorter release];
[subjectSorter release];
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
...
- (void)dealloc {
[activeSubjects release];
[activeCategories release];
[categories autorelease];
[subjects autorelease];
[quotes autorelease];
[quoteMaps autorelease];
[navigationController release];
[window release];
[super dealloc];
}
Here is the getInitialDataToDisplay:
+ (void) getInitialDataToDisplay:(NSString *)dbPath {
// Use this section to bring in database and populate the array
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
QuotesAppDelegate *appDelegate = (QuotesAppDelegate *)[[UIApplication sharedApplication] delegate];
//appDelegate.categories = [appDelegate.categories sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
//POPULATE THE SUBJECT
FMResultSet *result_subjects = [database executeQuery:#"select * from SUBJECT"];
while([result_subjects next]) {
NSInteger primaryKey = [result_subjects intForColumn:#"SUBJECT_ID"];
Subject *sub = [[Subject alloc] initWithPrimaryKey:primaryKey];
sub.title = [result_subjects stringForColumn:#"SUBJECT"];
sub.category_title = [result_subjects stringForColumn:#"CATEGORY"];
sub.active = [result_subjects intForColumn:#"ACTIVE"];
sub.isDirty = NO;
[appDelegate.subjects addObject:sub];
[sub release];
}
FMResultSet *result_categories = [database executeQuery:#"select distinct category from SUBJECT"];
while([result_categories next]) {
Category *cat = [[Category alloc] init];
cat.category_title = [result_categories stringForColumn:#"CATEGORY"];
NSLog(#"loading category: %#", cat.category_title);
QuotesAppDelegate *appDelegate = (QuotesAppDelegate *)[[UIApplication sharedApplication] delegate];
for (Subject *sb in appDelegate.subjects){
if([cat.category_title isEqualToString:sb.category_title]){
[cat.subjects addObject:sb];
NSLog(#" Adding subject: %# cat.subjects.count=%i", sb.title, cat.subjects.count);
}
}
[appDelegate.categories addObject:cat];
[cat release];
}
//POPULATE THE QUOTES
FMResultSet *result_quotes = [database executeQuery:#"select * from QUOTE"];
while([result_quotes next]) {
Quote *sub = [Quote alloc];
sub.quote_id = [result_quotes stringForColumn:#"QUOTE_ID"];
sub.quote_date = [result_quotes stringForColumn:#"DATE"];
sub.title = [result_quotes stringForColumn:#"DESC1"];
sub.desc2 = [result_quotes stringForColumn:#"DESC2"];
sub.excerpt = [result_quotes stringForColumn:#"EXCERPT"];
sub.note = [result_quotes stringForColumn:#"NOTES"];
sub.isDirty = NO;
[appDelegate.quotes addObject:sub];
[sub release];
}
//POPULATE THE QUOTE_MAPS
FMResultSet *result_quote_map = [database executeQuery:#"select * from QUOTE_MAP"];
while([result_quote_map next]) {
QuoteMap *sub = [QuoteMap alloc];
sub.quote_id = [result_quote_map stringForColumn:#"QUOTE_ID"];
sub.quote_map_id = [result_quote_map stringForColumn:#"QUOTE_MAP_ID"];
sub.subject_id = [result_quote_map stringForColumn:#"SUBJECT_ID"];
sub.isDirty = NO;
[appDelegate.quoteMaps addObject:sub];
[sub release];
}
[database close];
NSLog(#"Count of categories: %i", appDelegate.categories.count);
NSLog(#"Count of subjects: %i", appDelegate.subjects.count);
NSLog(#"Count of quotes: %i", appDelegate.quotes.count);
NSLog(#"Count of quoteMaps: %i", appDelegate.quoteMaps.count);
}
Here is the getDbPath:
- (NSString *) getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"reference.db"];
}
Sometimes, the best thing to do is build->analyze ( cmd shift b ). This will point out your bug right away in almost all cases.
Best of luck!
categories = [[NSMutableArray alloc] init];
.
.
//Initialize the Category array.
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
self.categories = tempArray;
[tempArray release];
u've setup categories, then setup the tempArray, replaced the one in categories with it thus making a leak, then released the temp arrayObject, which what categories is now also pointing on, so unless "self.categories" is a retained property it will be a zombie. there seems to be something wrong there.
I may need to see some more of your code (the property declarations and their synthesis to make sure.
is the Zombie called on "getInitialDataToDisplay" or on "getDBPath"
try dividing it on 2 lines to know pin point more
I think you have not declare Category as retained property in .h file.If not, add following line in your .h file
#property (nonatomic, retain) NSArray Category;
And synthesize the property in .m as-
#synthesize Category;
I think it will help ....
i have leaks in this code. The performane tool leaks tell me that this is in this line:
NSArray *fakeData = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"FakeData" ofType:#"plist"]];
I can't find out what is going on. The plist that i am loading have 3 NSDictionary Elements, so same as leaks in screenshot. Each Dictionary has 3 strings.
The entire code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Ładowanie danych
if (![[FlickrFetcher sharedInstance] databaseExists]) {
NSArray *fakeData = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"FakeData" ofType:#"plist"]];
for (NSDictionary *element in fakeData) {
//Wypełnianie CoreData danymi
Photo *newPhoto = (Photo *)[NSEntityDescription insertNewObjectForEntityForName:#"Photo"
inManagedObjectContext:[[FlickrFetcher sharedInstance] managedObjectContext]];
NSLog(#"Creating Photo: %#", [element objectForKey:#"name"]);
[newPhoto setName:[element objectForKey:#"name"]];
[newPhoto setImageURL:[element objectForKey:#"path"]];
NSLog(#"Person is: %#", [element objectForKey:#"user"]);ŕŕŕ
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", [element objectForKey:#"user"]];
NSMutableArray *peopleArray = (NSMutableArray *)[[FlickrFetcher sharedInstance] fetchManagedObjectsForEntity:#"Person"
withPredicate:predicate];
NSEnumerator *enumerator = [peopleArray objectEnumerator];
Person *person;
BOOL exists = FALSE;
while (person = [enumerator nextObject]) {
NSLog(#"Person is: %#", person.name);
if ([person.name isEqualToString:[element objectForKey:#"user"]]) {
exists = TRUE;
NSLog(#"-- Person exists: %#", person.name);
[newPhoto setOwner:person];
}
}
if (!exists) {
Person *newPerson = (Person *)[NSEntityDescription insertNewObjectForEntityForName:#"Person"
inManagedObjectContext:[[FlickrFetcher sharedInstance] managedObjectContext]];
[newPerson setName:[element objectForKey:#"user"]];
NSLog(#"Person created: %#", newPerson.name);
[newPhoto setOwner:newPerson];
}
NSError *error;
if (![[[FlickrFetcher sharedInstance] managedObjectContext] save:&error]) {
NSLog(#"Unresolved error %# %#", error, [error userInfo]);
exit(-1);
}
[fakeData release];
}
}
//Person Navigation Controller
personNavigationController = [[UINavigationController alloc] init];
PersonListViewController *personListViewController = [[PersonListViewController alloc] initWithStyle:UITableViewStylePlain];
personListViewController.title = #"Contacts";
[personNavigationController pushViewController:personListViewController animated:NO];
[personListViewController release];
//Recent Photo Navigation Controller
recentPhotoNavigationController = [[UINavigationController alloc] init];
RecentPhotoViewController *recentPhotoViewController = [[RecentPhotoViewController alloc] init];
recentPhotoViewController.title = #"Recent";
UITabBarItem *item = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemRecents tag:1];
recentPhotoViewController.tabBarItem = item;
[item release];
[recentPhotoNavigationController pushViewController:recentPhotoViewController animated:NO];
[recentPhotoViewController release];
//Tab Bar Controller
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:
personNavigationController,
recentPhotoNavigationController,
nil];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
return YES;
}
It looks like your fakeData array is being released inside of the for loop, which seems problematic on several levels. You probably meant to release it when the loop has exited. From Leaks' perspective, the for loop might never be entered, in which case the object would be leaked.
I have a mapkit / view and it works fine - but I scroll around and after 2 - 10 moves my app crashed... and this only with a "interrupted".
Here is part of my code. I think it's a problem with the background threads and an array release / override problem.
Some background info: I generate a "session" key (MapKey) on mapview startup and save on the serverside a pin. The XML includes only new pins for a faster response and shorter XML.
// Update map when the user interacts with it
- (void)mapView:(MKMapView *)aMapView regionDidChangeAnimated:(BOOL)animated
{
MyAnnotation *annotation = [[MyAnnotation alloc] init];
MyAnnotation *ann = [[MyAnnotation alloc] init];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *postBody = [[[NSString alloc] initWithFormat:#"single=0&lat=%f&lng=%f&sid=%#", mapView.centerCoordinate.latitude, mapView.centerCoordinate.longitude, [prefs stringForKey:#"MapKey"], [prefs stringForKey:#"MapKey"]] autorelease];
[self performSelectorInBackground:#selector(getMark:) withObject:postBody];
}
// make post and interact with verarbeiten
-(void) getMark:(NSString *)postBody
{
NSAutoreleasePool *ccpool = [[NSAutoreleasePool alloc] init];
NSString *urlStr = [[[NSString alloc] initWithFormat:#"http://URL/get.php"] autorelease];
NSMutableURLRequest *request;
NSData *postData = [postBody dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSURLResponse *response;
NSData *dataReply;
id stringReply;
request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString:urlStr]];
[request setHTTPMethod: #"POST"];
[request setHTTPBody:postData];
[request setValue:#"text/xml" forHTTPHeaderField:#"Accept"];
dataReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
stringReply = (NSString *)[[[NSString alloc] initWithData:dataReply encoding:NSUTF8StringEncoding] autorelease];
[self performSelectorInBackground:#selector(verarbeiten:) withObject:stringReply];
[ccpool release];
}
//generate annotations array with annotations an set it to mapview
-(void) verarbeiten:(NSString *)stringReply
{
NSAutoreleasePool *bbpool = [[NSAutoreleasePool alloc] init];
CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithXMLString:stringReply options:0 error:nil] autorelease];
NSMutableArray* annotations = [[NSMutableArray alloc] init];
NSArray *resultNodes = nil;
resultNodes = nil;
resultNodes = [rssParser nodesForXPath:#"//place" error:nil];
for (CXMLElement *resultElement in resultNodes)
{
MyAnnotation *ann = [[MyAnnotation alloc] init];
ann.title = [[resultElement childAtIndex:3] stringValue];
ann.subtitle = [[resultElement childAtIndex:5] stringValue];
ann.currentPoint = [NSNumber numberWithInt:[[[resultElement childAtIndex:1] stringValue] intValue]];
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = [[[resultElement childAtIndex:9] stringValue] floatValue];
region.center.longitude = [[[resultElement childAtIndex:7] stringValue] floatValue];
ann.coordinate = region.center;
//[mapView addAnnotation:ann ];
[annotations addObject:ann];
}
[mapView addAnnotations:annotations ];
[annotations release];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[bbpool release];
}
- (MKAnnotationView *) mapView:(MKMapView *)mV viewForAnnotation:(MyAnnotation *) annotation
{
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"de.my.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = NO;
pinView.userInteractionEnabled = YES;
UIButton *btnVenue = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
btnVenue.tag = [annotation.currentPoint intValue];
[btnVenue addTarget:self action:#selector(showLinks:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = btnVenue;
}
else
{
[mapView.userLocation setTitle:#"You are here"];
}
return pinView;
}
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate, title, subtitle,currentPoint;
-(void)dealloc
{
[title release];
[subtitle release];
[super dealloc];
}
#end
#import <Foundation/Foundation.h>
#import <MapKit/MKAnnotation.h>
#interface MyAnnotation : NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSNumber *currentPoint;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property(nonatomic, retain) NSNumber *currentPoint;
#end
Just a thought: since -[MKMapView addAnnotations:] (potentially) performs UI modifications, you may want to call it in the main thread:
[mapView performSelectorOnMainThread: #selector(addAnnotations:) withObject: annotations waitUntilDone: YES];