Cell Data not showing properly in table view swif4 - swift4.1

I am using table view inside table view I have used some views and then I used cell but when i running in simulator its content not showing properly
I added screenshot please check it.
func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return tc_array.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
print(b_description.bounds.size.height)
return 200 + b_description.bounds.size.height
// return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : TermCell = tableView.dequeueReusableCell(withIdentifier: "TermCell", for : indexPath as IndexPath) as! TermCell
cell.tc_lebel.text! = tc_array[indexPath.row]
print(cell.tc_lebel.text!)
return cell
}
new image click on it
2: https://i.stack.imgur.com/Lwd8o.png . check it new image
[1]: https://i.stack.imgur.com/I9rYO.png constraint image

If you have placed your constraints correctly, I would suggest removing
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
print(b_description.bounds.size.height)
return 200 + b_description.bounds.size.height
}
And when you setup your view, in viewDidLoad you should add this for automatic row dimension
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = yourAverageCellRowHeight

Related

I want to set collectionview height with maxY of last collectionviewcell! But why SE simulator doesn't work?

I want to set collectionview height with last item's maxY (not scrollable collectionview / grid collectionview / fixed width&height).
I get last index of item and get last item's layout using collectionView.layoutAttributesForItem(at: lastIndex)
and get maxY of the item and set collectionviewHeight to maxY.
But only SE simluator can't find correct maxY of last item?!
I don't know why SE simluator can't find correct maxY of last collectionview cell...
Here is my code (full code at github):
class CheckListTableViewCell: UITableViewCell {
var book = Book()
#IBOutlet weak var bookNameLabel: UILabel!
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var collectionViewHeight: NSLayoutConstraint!
var estimateWidth = 30.0
var cellMarginSize = 3.0
override func awakeFromNib() {
super.awakeFromNib()
setCollectionView()
}
func setCollectionView(){
collectionView.register(UINib(nibName: "PageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "PageCollectionViewCell")
self.translatesAutoresizingMaskIntoConstraints = false
if let flow = collectionView.collectionViewLayout as? UICollectionViewFlowLayout{
flow.minimumInteritemSpacing = CGFloat(self.cellMarginSize)
flow.minimumLineSpacing = CGFloat(self.cellMarginSize)
}
}
class func instanceFromNib( _ book:Book)->CheckListTableViewCell{
let cell = UINib(nibName: "CheckListTableViewCell", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! CheckListTableViewCell
cell.book = book
cell.bookNameLabel.text = book.title
cell.collectionView.reloadData()
cell.setCollectionViewHeight()
cell.selectionStyle = UITableViewCell.SelectionStyle.none
return cell
}
}
extension CheckListTableViewCell:UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return book.pageList.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PageCollectionViewCell", for: indexPath) as? PageCollectionViewCell else{
return UICollectionViewCell()
}
let page = book.pageList[indexPath.row]
cell.pageNumberLabel.text = page.pageNumber
return cell
}
}
extension CheckListTableViewCell:UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = self.calculateWith()
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let page = book.pageList[indexPath.row]
RealmManager.shared.changeIsReadOfPage(title: book.title, pageNumber: page.pageNumber, isRead: !page.isRead)
if let cell = collectionView.cellForItem(at: indexPath) as? PageCollectionViewCell{
cell.toggle(isRead:!page.isRead)
}
}
}
extension CheckListTableViewCell{
func calculateWith() -> CGFloat {
let estimatedWidth = CGFloat(estimateWidth)
let cellCount = floor(CGFloat(collectionView.frame.size.width / estimatedWidth))
let margin = CGFloat(cellMarginSize * 2)
let width = (collectionView.frame.size.width - CGFloat(cellMarginSize) * (cellCount - 1) - margin) / cellCount
return width
}
// it is very clean & simple to set collectionview height with maxY of last collectionview cell
// But only SE Simulator maxY is not correct why????!
func setCollectionViewHeight(){
let lastIndex = IndexPath(item: book.pageList.count-1, section: 0)
if let att = collectionView.layoutAttributesForItem(at: lastIndex){
collectionViewHeight.constant = att.frame.maxY
}
}
}

MapKit not showing custom Annotation pin image on iOS9

My code worked fine from iOS 7 to 8. With the update yesterday the custom images on my pins were replaced by the standard pin image.
Any suggestions?
My code:
extension ViewController: MKMapViewDelegate {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView! {
if annotation is MKUserLocation {
return nil
}
let reuseId = String(stringInterpolationSegment: annotation.coordinate.longitude)
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.image = getRightImage(annotation.title!!)
}
let button = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = button
return pinView
}
}
The function to get the image returns a UIImage based on the name:
func getRightImage (shopName:String)-> UIImage{
var correctImage = UIImage()
switch shopName
{
case "Kaisers":
correctImage = UIImage(named: "Kaisers.jpg")!
default:
correctImage = UIImage(named: "sopiconsmall.png")!
}
return correctImage
}
No the map looks like this:
Instead of creating an MKPinAnnotationView, create a plain MKAnnotationView.
The MKPinAnnotationView subclass tends to ignore the image property since it's designed to show the standard red, green, purple pins only (via the pinColor property).
When you switch to MKAnnotationView, you'll have to comment out the animatesDrop line as well since that property is specific to MKPinAnnotationView.
Following code works perfectly on all iOS 6 to iOS 9 devices:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// create a proper annotation view, be lazy and don't use the reuse identifier
MKAnnotationView *view = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"identifier"];
// create a disclosure button for map kit
UIButton *disclosure = [UIButton buttonWithType:UIButtonTypeContactAdd];
[disclosure addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(disclosureTapped)]];
view.rightCalloutAccessoryView = disclosure;
view.enabled = YES;
view.image = [UIImage imageNamed:#"map_pin"];
return view;
}
For Swift 4
func mapView(mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = String(stringInterpolationSegment: annotation.coordinate.longitude)
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.image = getRightImage(annotation.title!!)
}
let button = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = button
return pinView
}

How to calculate content height of WKWebView?

For UIWebView, we can get content height by this:
[webView stringByEvaluatingJavaScriptFromString:#"document.body.offsetHeight"]
But WKWebView doesn't have this method and webView.scrollView.contentSize.height is not right.
(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
}
Thank you for your help!
I solved this problem with KVO.
First, addObserver for WKWebView's scrollView's contentSize like this:
addObserver(self, forKeyPath: "webView.scrollView.contentSize", options: .New, context: nil)
And next, receive the change like this:
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if keyPath == "webView.scrollView.contentSize" {
if let nsSize = change[NSKeyValueChangeNewKey] as? NSValue {
let height = nsSize.CGSizeValue().height
// Do something here using content height.
}
}
}
It's easy to get webview's content height.
Don't forget to remove observer:
removeObserver(self, forKeyPath: "webView.scrollView.contentSize", context: nil)
I worte this line in deinit.
EDIT:
To get the best possible height calculation, in the end I did a few things to get the best height:
I set the size of the webview to be really large and then load the content.
Once the content is loaded (KVO notification) I resize the view using the method below.
I then run the size function again and I get a new size and resize my view once again.
The above got the most accurate results for me.
ORIGINAL:
I've tried the scroll view KVO and I've tried evaluating javascript on the document, using clientHeight, offsetHeight, etc...
What worked for me eventually is: document.body.scrollHeight. Or use the scrollHeight of your top most element, e.g. a container div.
I listen to the loading WKWebview property changes using KVO:
[webview addObserver: self forKeyPath: NSStringFromSelector(#selector(loading)) options: NSKeyValueObservingOptionNew context: nil];
And then:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if(object == self.webview && [keyPath isEqualToString: NSStringFromSelector(#selector(loading))]) {
NSNumber *newValue = change[NSKeyValueChangeNewKey];
if(![newValue boolValue]) {
[self updateWebviewFrame];
}
}
}
The updateWebviewFrame implementation:
[self.webview evaluateJavaScript: #"document.body.scrollHeight" completionHandler: ^(id response, NSError *error) {
CGRect frame = self.webview.frame;
frame.size.height = [response floatValue];
self.webview.frame = frame;
}];
You can get it like this:
self.webview.navigationDelegate = self;
- (void)webView:(WKWebView *)webview didFinishNavigation:(WKNavigation *)navigation{
// webview.scrollView.contentSize will equal {0,0} at this point so wait
[self checkIfWKWebViewReallyDidFinishLoading];
}
- (void)checkIfWKWebViewReallyDidFinishLoading{
_contentSize = _webview.scrollView.contentSize;
if (_contentSize.height == 0){
[self performSelector:#selector(WKWebViewDidFinishLoading) withObject:nil afterDelay:0.01];
}
}
WKWebView didn't finish loading, when didFinishNavigation is called - Bug in WKWebView?
WKWebView doesn't use delegation to let you know when content loading is complete.
You can create a new thread to check the status of WKWebView.
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), {
while(self.webView?.loading == true){
sleep(1)
}
dispatch_async(dispatch_get_main_queue(), {
print(self.webView!.scrollView.contentSize.height)
})
})
}

switch statement gone wrong - swift language

in Obj-c i made a switch statement which i used to move around in my app for iPad using UIsplitviewcontroller
now i want to do the same in swift... i tried for a couple of hours and now the only thing i haven't been able to try is the code because it says some sort of compile error
anyway
here's what i got in Obj-c
-(void)initialSite:(int)viewId {
UIViewController *viewController;
switch (viewId) {
case 0:{
viewController = self.initital;
NSString *star = [NSString stringWithFormat:#"Velkommen til %#'s Bog",[data valueForKey:#"navn"]];
self.navigationItem.title = star;}
break;
case 1:{
viewController = self.startSide;
NSString *start = [NSString stringWithFormat:#"%#'s Bog, start-side",[data valueForKey:#"navn"]];
self.navigationItem.title = start;}
break;
}
[self showChildViewController:viewController];
}
and here's what i come up with so far in swift. still new to this and to understand it is a little hard even tho i have the swift programming language book
here's what i got so far in swift
let viewController = UIViewController()
switch viewController {
case "initial":
let initial : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc0 : UIViewController = initial.instantiateViewControllerWithIdentifier("initial") as UIViewController
self.presentViewController(vc0, animated: true, completion: nil)
let rowData: NSDictionary = self.menuItemArray[indexPath.row] as NSDictionary!
self.navigation.title = rowData["navn"] as? String
case "startSide":
let startSide : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc1 : UIViewController = startSide.instantiateViewControllerWithIdentifier("startSide") as UIViewController
let rowData: NSDictionary = self.manuItemArray[indexPath.row] as NSDictionary!
self.presentViewController(vc1, animated: true, completion: nil)
self.navigation.title = rowData["navn"] as? String
default:
}
the error is : Expected declaration at the line with
let viewController = UIViewcontroller()
Let's start with your Obj-C implementation:
-(void)initialSite:(int)viewId
{
UIViewController *viewController;
switch (viewId)
{
case 0:
{
viewController = self.initital;
NSString *star = [NSString stringWithFormat:#"Velkommen til %#'s Bog",[data valueForKey:#"navn"]];
self.navigationItem.title = star;
}
break;
case 1:
{
viewController = self.startSide;
NSString *start = [NSString stringWithFormat:#"%#'s Bog, start-side",[data valueForKey:#"navn"]];
self.navigationItem.title = start;
}
break;
}
[self showChildViewController:viewController];
}
Now this same snippet in Swift:
func initialSite(viewID:Int)
{
var viewController : UIViewController?
switch (viewID)
{
case 0:
viewController = self.initial
let navn = self.data["navn"] as? String
let star = "Velkommen til \(navn)'s Bog"
self.navigationItem.title = star
case 1:
viewController = self.startSide
let navn = self.data["navn"] as? String
let star = "\(navn)'s Bog, start-side"
self.navigationItem.title = star
default:
viewController = nil
// do nothing
}
self.showChildViewController(viewController)
}
The main thing you have to remember is the difference with var vs let. Typically you will use let to create things unless those things will have their value changed later, which you use var.
The other thing is the use of optionals, with the ? suffix. This is when the value may be nil (unset), otherwise it must contain a value.
Looks like SiLo beat me to it. Anyway I have my solution so I will post it. This is how I would do it:
func initialSite(viewId: Int) -> () {
var viewController: UIViewController?
let dataValue = data["navn"];
var start: String?
switch viewId {
case 1:
viewController = self.initital
start = "Velkommen til \(dataValue)'s Bog"
case 2:
viewController = self.startSide
start = "\(dataValue)'s Bog, start-side"
default:
break;
}
self.navigationItem.title = start!
showChildViewController(viewController!)
}

Change color title UITable static section

I have two UITable static sections in my application with both different headers.
The color of the header must be changed because the custom background.
How can I do this solution like ( link ) in my MonoTouch application?
Because I use static sections, I don't have a UITableViewSource where I can do stuff in.
My solution (thanks to Krumelur)
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSecion (UITableView tableview, int section)
{
UIView view = new UIView (new RectangleF (0, 0, 300, 0));
view.BackgroundColor = UIColor.Clear;
UILabel label = new UILabel (new RectangleF (15, 5, 300, 25));
label.BackgroundColor = UIColor.Clear;
label.TextColor = UIColor.White;
label.ShadowColor = UIColor.Black;
label.ShadowOffset = new SizeF(0, 1);
label.Font = UIFont.BoldSystemFontOfSize(18);
if (section == 0) {
label.Text = "First section";
} else {
label.Text = "Second section";
}
view.AddSubview(label);
return view;
}
You'll have to export the missing method in your controller. Something like:
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSection(UITableView tableview, int section
{
// return your UIView with whatever background color here
}
Note that you cannot change the color of the predefined view but have to return an entire view instead.

Resources