Probably a bit hard to explain without diagrams but here goes.
Swift, iOS 8 using Storyboards.
I want to be able to load a view in the storyboard, load values into textfields, populate the TableView, etc. as if I was navigating to it normally but not actually showing the view to the user.
The view is an invoice template that I can capture and turn into a PDF but that relies on the fact that the view is populated with values, i.e. Loading the view.
I can call the PDF capture function without going to the view but the view is empty of values and table data. So far I've tried :-
let vc = storyboard?.instantiateViewControllerWithIdentifier("orderform") as OrderForm
vc.createPDFfromUIView(vc.view, aFilename: "test.pdf")
Thanks,
Anthony
Try setting
vc.view.hidden = true
before you present it.
I got it to work in the end. I had to move code that was in
viewDidLoad
to
ViewDidLayoutSubviews
on the OrderForm for the view to complete before taking a snap shot. Then the code below worked.
// Instatiate OrderForm viewController
let vc = storyboard?.instantiateViewControllerWithIdentifier("orderform")
as OrderForm
// Copy arrray items to OrderForm viewController for tableView data
vc.Orders = Orders
// Create PDF of OrderForm view using UIGraphicsBeginPDFContextToData
vc.createPDFfromUIView(vc.view, aFilename: "\(companyTextField.text).pdf")
// Call UIActivityViewController and attach PDF
share(sender)
Thanks,
Anthony
Related
I am designing an iPhone application with a home page. This page has multiple buttons (6) that go to different things.
2 buttons are a simple view that just have some information and go back to the home screen. The next button opens up an email and I believe that will just be one view, so not a whole lot different than the other two.
Here is where it gets complicated. One button will take a picture, and another will select one from the library. Once that is done it will edit it and create an object that I will create. That object will be stored in an array, which will be opened by the last button one the home page and a UITableViewController will control that.
My first question is should I use a navigation based view controller or just a view controller that I can create myself? Or should I use something that I don't even know about?
Please Help!!! And if you help a sincere thank you!
EDIT:
Well i tried it my own way first and the only issue i'm having is this code
- (void) displayView:(int)intNewView {
NSLog(#"%i", intNewView);
[home.view removeFromSuperview];
Instructions *i = [[Instructions alloc]init];
instructions = i;
[self.view insertSubview:instructions.view atIndex:0];
}
It is in my SwitchClass, which controls the Main Window's view. I know it is working there because when it first runs the switch class directs it to the home screen. I know the method is being called because the console is displaying the NSLog thing, but it just won't switch.
Aside from the fact that you have 6 buttons, I would try and use a UITabBarController for what you are trying to do; it would seem more natural to me (but you should find a way to reduce you 6 button to 5, otherwise they will not be displayed all at once).
Otherwise, a UINavigationController seems fine to me. For each button you push a new controller to deal with that button functionality, then you pop back. It should work easily.
EDIT:
have you tried with?
[self.view addSubview:instructions.view];
Your first question Yes you should use navigation based controller ... so when you press any button will open the other view controller with animation.. also Navigation Based Controller keep track of the parent controller if you have any created objects will be retained in the parent view controller that is the root of the Navigation.
here is the steps that you should use.
1-Create Navigation controller in the main application delegate and make it's root is the view controller.
2-when you push the view controller that have 6 buttons .
3- you can check this link for get photo album also if you have changed the source type to camera then you can get the image...
Photo Libaray
4- once you get the image you can add it to NSMutableArray that exist on the NavigationViewController root in your case will be the view which have the 6 buttons.
5-sice every time you want to view the array which contain the photos you will initialize the data source of the uitableviewcontroller with the array that you save photos on.
Thanks
I think the problem is coming from one of two places:
As I understand it, these are all different View Controllers, correct? And they have their own xib files? If that is true, then calling:
Instructions *i = [[Instructions alloc]init];
is insufficient. You need to use
Instructions *i = [[Instructions alloc] initWithNibNamed:#"Instructions"];
in order to include that view that you have already constructed in the interface builder.
The other thing I see potentially going wrong is that you are inserting all the views at the same index. Think of the index as a layer in photoshop. If you want the new view to be visible overtop of the last one, then it needs to be a higher index. This is handled automatically if you use addSubview: instead of insertSubview: atIndex:
I have a tableview with custom section headers. The view for the section header is defined in the storyboard and wired to an instance variable. Is there a way to request a new instance of the view from the storyboard?
In the past I have done this by having the section header defined in its own xib file and getting a new instance by using
[[NSBundle mainBundle] loadNibNamed:#"TimerViewSectionHeader" owner:self options:nil];
UIView *newHeaderView = self.sectionHeaderView;
I dont' think there is a way to do that. Best bet is to put the tableview custom header view in a separate nib and load it like you did in your code sample whenever you need to use it.
I tried to do the same thing and ran into the same problem.
I like to work with storyboards a lot and was impressed how fast I could create a working UI. However, as soon as you need to re-use views it makes a lot of sense to put those into a separate nib along with its UIViewController subclass.
You can then place a generic UIView in all the places where your re-used view should go and add the view using your ViewController:
[myReusableViewController loadView];
[myReusableViewController viewDidLoad]; // You have to handle view callbacks yourself.
[self.myReusableViewPlaceholder addSubview:myResusableViewController.view];
[myReusableViewController viewWillAppear:YES];
So to sum it up:
Use storyboard, it's great
Create the scaffold of your application in the storyboard, along with any static view (like About screens etc.)
Create re-used views in a custom nib + UIViewController subclass and add UIView placeholders in your storyboard.
In another answer I thought about some Pros and Cons of Storyboard
The solution I've come up with for this is as follows:
I have a tableview with multiple prototype cells that displays complex data. There is a segue to a detail view, and a transaction process view.
This first tableview has a search button that displays a new tableview with the results. It needs the same functionality as the main tableview that pushes it; including segues to the detail and transaction progress views so:
On storyboard, select and copy your main tableview. Deselect and paste. Create a push segue from your main tableview to your 2nd tableview; or from where ever you want to navigate to it from. Modify the 2nd tableview as you like. IE: If it requires some UI changes no problem.
Create a new viewcontroller class that is a subclass of the viewcontroller running the main tableview.
Override the data delegate in your subclass to serve up the subset of data you want.
Back in the storyboard, select your 2nd tableview controller and in the identity inspector select your subclass as the custom class.
For this solution to work smoothly, your app really needs to be managing data for the views. You could use prepareforsegue to pass data from 1st tableview to the second, but I've found the app data model far more flexible from numerous points of view.
Unless you have buttons that push to the sub views via segue, your subclass will need to override functions that push via segues with identities. NB Segues must have unique identifiers if you id them at all.
It took a lot of trial and error to figure this out, but once you understand the concept, it's a relatively smooth solution that is quite adaptable and not so bad to implement.
I am not sure about just views, but the way that I was able to get view controllers out of my storyboard is as follows.
UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"IdentifierName"];
From here, perhaps you might be able to use this similarly to how it was once done with nibs.
I've been able to reuse a view in the storyboard just by connecting a transition from one tableview into the one I want to reuse.
so my tableview that I want to reuse is pointed to twice.
It sort of works but the problem I'm running into it setting a variable (using instantiateViewControllerWithIdentifier) in my app delegate to my table view that is getting reused.
It seems that if I reuse it, the storyboard is creating 2 instances of my tableview and the one I get with instantiateViewControllerWithIdentifier isn't the one I want.
I'm not really sure if this is the proper way to do it. But I assume many others are doing this somehow. With the custom table cells in storyboard I suspect lots of people want to reuse their views.
For example: We want to reuse the view(include subviews) in storyboard shown below.
The best solution I know so far is clip and paste the view related code to the New Singe View file without losing the information.
Detailed steps are as follows
Step 1: Rename the view we want reuse. Just prepare for step 2.
Step 2: Open storyboard as source code in order to clip the XML code we need
Step 3、4: Search and clip the code we need
Step 4.5(Not needed): Open as Interface Builder to see the view removed
Step 5、6: New XXX.xib and paste the code we clipped just now
Step 7: Important. Insert code<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> to XXX.xib source code.
Warning: Do this before open it as Interface Builder! Otherwise, you will see wrong size and layout waring.
[![step 7][9]][9]
Step 8: New XXX.swift to connect the XXX.xib
[![step 8][10]][10]
Step 9: Add the view anywhere we want
[![step 9][11]][11]
I get warning: "You need at least 10 reputation to post more than 8 links."
Can you support me to upload the remaining 3 screenshots?
I am pulling my hair out on this one. I have a NavigationController with two levels of TableViews. Each TableView is in its own NIB file. The first level simply displays a list. Upon selecting a cell, it takes the user to a second level TableView with a more detailed list. It is on this second level TableView that I want to display a search bar (actually I am using a SearchDisplayController as well). I have added it to the TableView because I want the SearchBar to scroll with the table.
Below, I am displaying two screenshots. The first is the second level tableview in InterfaceBuidler. The second is the second level tableview at runtime. For some reason, the SearchBar doesn't display at runtime.
I have tried creating a completely new project from scratch and the same things happens. I don't understand why the SearchBar doesn't display on a NIB pushed on the NavigationController.
Before you ask, if I put the SearchBar on the first level TableView, it shows up just fine. Yes, I am adding it to the TableView itself, so it is a part of the view that should be displayed.
Help! What am I doing wrong?
This is what actually displays after the XIB is pushed...
Okay, I'm going to have to answer my own question. I thought about deleting it, but perhaps this could help someone else. I really pulled my hair out on this one. It wasn't because of anything I was doing wrong so much as a fundamental misunderstanding of how iPhone development works.
In a nutshell, the problem was with this line of code, which instantiated the TableViewController:
self.downloadDetailViewController = [[DownloadDetailTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
When you use XCode to create a new class, you can use the following:
"Add -> New File -> Cocoa Touch Class -> UIViewController subclass -> UITableViewController
subclass AND With XIB for user interface"
The problem is that the NIB has absolutely nothing to do with the UITableViewController until you tell your code to use it. To me, this seems like a bug in XCode or at the very least something that is counterintuitive. When the development environment creates all three files together, it would only make sense that they would work together, but they don't.
Instead, the solution is to modify the line of code as follows:
self.downloadDetailViewController = [[DownloadDetailTableViewController alloc] initWithNibName:#"SecondaryView" bundle:[NSBundle mainBundle]];
Hopefully this can help someone else...
You could also set Nib Name property on your Download View Controller under the Tab Bar Controller, in fact that and coupled with setting the class with your class name will automatically create the view for you and you don't have to manually create it.
I think the problem is that you are adding the searchbar to the tableView, so it is not displaying.
Try to add that searchBar with out adding to the table view, that means move the table view some what down and add the search bar to the view(not the tableview).
So I've got one main view with some images on it, and when someone touches one of the images, the image will return an ID number to this main view and then this view will present a modal view controller to display a larger version of this image. But the current way I'm doing it, the function on the modal controller is getting there before the NIB is loaded or something, because when (in that function) i tell it to change the text of some IB labels they are NULL. However, when I, say, press a button that calls a function to do the same it does it just fine. Here's what I'm doing now:
What is the best way to send data to a modal view controller while presenting it? Thanks so much!
- (void)photoViewWasTouchedWithID:(int)imgID {
[self presentModalViewController:singlePhotoView animated:YES];
[singlePhotoView showImageWithID:imgID];
}
Instead of doing the view object manipulation in showImageWithID:, store the parameter into a member variable. Then do your setup work in viewWillAppear, and your view objects should be instantiated.
I was helped here a while ago about loading images from an array, but would like to know the exact details please.
Where does the code go if my app will be as simple as images that load from an array depending on whether the user chose the next or previous button? Does it go in the View Controller class?
What do I need if I literally just need one view which displays a full screen image and the image gets changed depending on the user choice, like I mentioned above?
Thanks in advance
Regards
The view controller is responsible for controlling the view (receiving events from it, doing something then passing back data to it).
That said you can store your array in the view controller or in some other model class. Either way the view controller will be responsible for taking an image from this array and giving it to the view when it receives user input.
You just need to place a UIImageView in your view controller's view. Then assuming you're using IB you create an IBOutlet property in your controller to have a handle on this image view.
Then you need to get events from your user (either a button, or some other touch) and assign it to an IBAction that your controller can handle. When you handle the action you can remove the old image and assign a new image from your array to your UIImageView.
That's about as detailed as I can go given your current question. If you need more information please give more detail.