I have an app where I have slider where I have used icarousel. Below slider I have list of events. When I click on event, it go to event details.
What I noticed is that my iPhone is restarting if I go to event details from list and click back button from the details screen.
This is happening with iPhone 6 & above devices only.
Click to see the stacktrace
As its big, I provide link.
Just to add, I have also used UIRefreshControl on UITableView. Below is the code I have used.
refreshControl = [[UIRefreshControl alloc]init];
[mainTableView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
-(void) refreshTable {
[indicator startAnimating];
indexCounter.text = #"0";
indexCounter.hidden = YES;
occasionsArray = [[NSMutableArray alloc] init];
actualOccasionsArray = [[NSMutableArray alloc] init];
mainOccasionsArray = [[NSMutableArray alloc] init];
[refreshControl endRefreshing];
[mainTableView reloadData];
[self fetchHomeScreenOccassions]; // this is where I call webservice
}
Congratulations. You have:
Found a crasher bug in the NSURLSession helper daemon
Managed to create an animation on a view or other item that is so huge that you crashed the window server.
I can't tell you exactly how your code managed to do either of those things, but... one thing I notice is that you're nuking the entire table view and then reloading it. That's not necessarily the best way to approach this problem. Instead, you should load the data, and (assuming it comes in a consistent order) iterate through the items in your existing array as you receive items, deleting anything that should have been received already and adding any new items that aren't in the array yet.
Related
I am working on implementing support for a CarPlay audio app, and am attempting to display listings in the simulator. I have implemented MPPlayableContentDataSource, but find that it is called inconsistently. It is called the first time the app is launched on a simulator, and if CarPlay is open on launch, I can make the first item display by scrolling up an otherwise empty listing to trigger a redraw.
CarPlay does not seem able to call the data source, however, and on a subsequent launch I see an empty screen or a spinner followed by the message Unable to connect to "AppName". I have tried different things but the main points are as follows:
In application: didFinishLaunchingWithOptions:
self.contentDataSource = [[MYContentDataSource alloc] init];
self.contentDelegate = [[MYContentDelegate alloc] init];
MPPlayableContentManager *contentManager = [MPPlayableContentManager sharedContentManager];
contentManager.dataSource = self.contentDataSource;
contentManager.delegate = self.contentDelegate;
[contentManager beginUpdates];
[contentManager endUpdates];
I've played around with beginUpdates endUpdates and reloadData methods of the content manager, but none of these result in the content datasource actually being called.
I've implemented numberOfChildItemsAtIndexPath and contentItemAtIndexPath in the datasource, which appear to be called correctly, although only on the first launch of the app on a fresh simulator.
The main points:
- (NSInteger)numberOfChildItemsAtIndexPath:(NSIndexPath *)indexPath {
return 3;
}
- (MPContentItem *)contentItemAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger categoryId = [indexPath indexAtPosition:0];
MPContentItem *contentItem = [[MPContentItem alloc] initWithIdentifier:[NSString stringWithFormat:#"CAT-%lu", (unsigned long)categoryId]];
contentItem.title = [NSString stringWithFormat:#"Category %lu", (unsigned long)categoryId];
contentItem.subtitle = #"Subtitle";
contentItem.playable = NO;
contentItem.container = YES;
}
I've also tried retaining (or not) the reference to the MPPlayableContentManager.
I have the same behavior on an actual head unit. Any help would be appreciated.
After banging my head against the wall for quite a while, I got the following answer from Apple. Turns out that MPRemoteCommandCenter and MPNowPlayingInfoCenter are needed for CarPlay to work.
1. Start responding to MPRemoteCommandCenter events at app launch
2. Set the MPNowPlayingInfoCenter dictionary at app launch
These are required for MPPlayableContentDataSource to function correctly.
They are mentioned in the doc, but it isn't clear that they are needed for the catalog display to work. That solved the problem.
I am making an application that is retrieving JSON data and placing it into a UITableView. I am just wondering what the best practice's are for dealing with failure to load data, no internet connection, etc. I have also implemented a pull to refresh on the table, so I want it to reload through that. As of right now I have everything working correctly, but it is my first time doing it so I am just wanting to see if I'm missing something.
Here is how I have it setup:
// Assume there are method's that retrieve the data
- (void)viewDidLoad
{
[self loadData];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.tintColor = [UIColor darkGrayColor];
[refreshControl addTarget:self action:#selector(reloadTable) forControlEvents:UIControlEventAllEvents];
self.refreshControl = refreshControl;
}
- (void)reloadTable
{
[self loadData];
if (self.jsonCodeData) {
[self.tableView reloadData];
[self.refreshControl endRefreshing];
} else {
[self.refreshControl endRefreshing];
}
}
So basically I load the data when the view load's and create/initialize a UIRefreshControl. The reloadTable method is where I implemented my answer to this question. Is that correct or is there a better way to do it? Also I am wanting there to be a filler "No Data: Pull to Refresh" type image when nothing is loaded. What is the best way to make that happen when I am using a UITableViewController? I just added another prototype cell that I marked to use for needing a refresh.
An issue that I am coming across right now is that I am having to pull to refresh twice if a user has no internet and then happen's to get it. They are having to pull it once to essentially get the data, but the if statement won't pass that time around. The next time they pull it will actually load the table.
The main point of this is just seeing if this is the best way to implement a failure on data retrieval.
- (void)viewDidAppear:(BOOL)animated
{
[super viewWillAppear:animated];
_datePicker = [[UIDatePicker alloc] init];
_datePicker.datePickerMode = UIDatePickerModeDate;
_datePicker.frame = CGRectMake(70, self.view.frame.size.height ,250,100);
_datePicker.alpha = 0;
[_datePicker addTarget:self action:#selector(saveDate:) forControlEvents:UIControlEventEditingDidEnd];
[self.view addSubview:_datePicker];
}
I'm trying to figure out where is my "unbounded memory growth" , I'm using ARC in my app. I have a few memory issues in my app and I'm trying to figure them out one by one.
While moving between 2 viewControllers I can clearly see a big increase in memory use, the main cause for it is the code I wrote here. What am I doing wrong, how can I release it and where?
Thanks
viewDidAppear: gets called every time the view appears (even if the controller has been initialized already). So each time the view appears you are allocating a new UIDatePicker without releasing the old one.
If your datePicker is defined as a #property with "retain" then I would use
self.datePicker = [[[UIDatePicker alloc] init] autorelease];
By using self.datePicker you are calling the synthesized setter which will automatically release the old value for you.
Alternatively you can move this initialization to initWithNibName: or viewDidLoad: instead, that way it will only get called once.
Try this out and see if it helps your memory.
(I'm assuming you're not using ARC, otherwise what I said won't really help you).
I made an app for iPhone. Now, I'm recreating it for iPad.
When the user selects the action button in the toolbar, a popover should show with a UIActivityViewController, but for some reason, it's taking about 10 seconds for it to show the first time. On iPhone, it takes about a second. It's the same code except for the popover.
I tried disabling the popover, but it still takes around 10 seconds to show.
Here is the code:
-(IBAction)Actions:(UIBarButtonItem*)sender
{
if ([activityPopover isPopoverVisible] == YES)
{
[activityPopover dismissPopoverAnimated:YES];
return;
}
UIWebView *currentWebView = ((TabView *)self.tabs[self.currentTabIndex]).webViewObject;
NSString *currentURL = (NSString*)[currentWebView request].mainDocumentURL;
if (currentURL == NULL) return;
BookmarkActivity *bookmarkActivity = [[BookmarkActivity alloc] init];
UIActivityViewController *sharing = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObject:currentURL] applicationActivities:#[bookmarkActivity]];
activityPopover = [[UIPopoverController alloc] initWithContentViewController:sharing];
[activityPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
I have tested on my iPad 3 and my iPad mini, both take awhile to present this.
How can I solve the problem?
Good question, I just had the same problem. It is not really solvable. However, you may improve the user experience by creating an activity indicator and then sending the initialization of the UIActivityViewController to the background:
-(void)openIn:(id)sender
{
// start activity indicator
[self.activityIndicator startAnimating];
// create new dispatch queue in background
dispatch_queue_t queue = dispatch_queue_create("openActivityIndicatorQueue", NULL);
// send initialization of UIActivityViewController in background
dispatch_async(queue, ^{
NSArray *dataToShare = #[#"MyData"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
// when UIActivityViewController is finally initialized,
// hide indicator and present it on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicator stopAnimating];
[self presentViewController:activityViewController animated:YES completion:nil];
});
});
}
It works like a charm. When the user touches the button, the activity indicator starts animating, thus indicating that the process will take a while.
I was having the same issue on iOS 7. When I removed UIActivityTypeAirDrop from the allowed activity types, however, the controller appears almost instantly.
Although these calls are already from the main thread, since iOS 7, wrapping some of those presentation calls in a dispatch block seems to greatly reduce the delay
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:activityViewController animated:YES completion:nil];
});
Had this issue myself recently. Would sometimes take nearly 4 or 5 seconds to pop up, which is a lifetime! Only the first time though. Subsequent calls were quick.
Also had a similar issue a couple of years back with the keyboard appearing slowly and someone produced a few lines of code added to the appdelegate that preloads the keyboard to get around that.
I used a similar approach here to preload the UIActivityViewController by placing this in the AppDelegate on startup. It's absolutely a hack which shouldn't be necessary but I couldn't find any other options.
let lagfreeAVC:UIActivityViewController = UIActivityViewController(activityItems: ["start"], applicationActivities: nil)
lagfreeAVC.becomeFirstResponder()
lagfreeAVC.resignFirstResponder()
I've been looking around for a good pattern to implement a insert then cancel pattern when working with a UINavigationBar and UITableView.
I have I have a "insert"button in my TeamsViewController navigation bar (screenshot)
Which when I run it runs this code:
-(void)insertTeam
{
if( !detailViewController ) {
detailViewController = [[TeamDetailViewController alloc] init];
}
if( !teams ) {
teams = [NSMutableArray array];
}
Team *team = [[Team alloc] init];
[teams addObject:team];
int lastIndex = [teams count];
[detailViewController setEditingTeam:[teams objectAtIndex:lastIndex - 1]];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[self presentModalViewController:navigationController animated:YES];
}
Which is great if the user fills out all the info, but if they hit cancel on the next view, there's an empty object in my arrary.
I'm sure there's a great pattern to achieve this but I've looked at all the TableView sample codes, two different ios books, and tried googling it, but haven't found a pattern for this.
My thought is something like the following:
When user cancels, set a canceled ivar in my Team object to YES
Back in my TeamsViewController, when the view appears check the last object in my teams array and see if it's property canceled is YES, if so remove that last object.
But this doesn't seem so slick and I was figuring there was some better way to achieve this. TIA.
I would be tempted to make the TeamsViewController a delegate of the TeamDetailViewController. The delegate would implement a method such as - (void)teamCreated:(Team *)team; and it would update the array. Since there seems to be no point to having a Team in the array that's incomplete, I would have the TeamDetailViewController create the Team and pass it back in the delegate call. On a cancel, there would be no need to do anything except pop the controller.