I am overriding the UIAlertView class with something similar seen in this tutorial
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-uialertview-custom-graphics/
So I am overriding the drawRect...
My problem is not actually customizing the alert itself, but rather the view background color behind the UIAlertView itself right now it is the standard black gradient that all UIAlertViews have... Any ideas on how to do this?
I took this approach and seems to work... In layoutSubview I am looping over the superviews subviews
for (UIView*superSub in self.superview.subviews) {
if ([superSub isMemberOfClass:[UIImageView class]]) {
superSub.backgroundColor = [UIColor colorWithRed:30/255. green:21/255. blue:4/255. alpha:1];
superSub.alpha = 0.77;
}
}
Related
During Xcode UI test, I found my custom view's (MenuViewButton) is un-hittable in a test, I could found it but cannot touch it. In debug , when I po isHittable in console, it returns false. However I'm not sure if this is the correct behavior.
Per this thread XCUIElement exists, but is not hittable said, isHittable is default false for custom view element, and default true for UIKit standard view. But I don't know if it is the same behavior in SwiftUI.
Since the way someView.isAccessibilityElement = true is not possible in SwiftUI. My question is how could I let my custom view became hittable? Then it could be tapped in a test.
private var aView: some View {
MenuViewButton(
image: Image("an image name"),
text: Text("a string")
)
.accessibility(identifier: "xxx name")
}
I also use force tap with coordinate in case tap() is not working, but to give a offset of normalizedOffset didn't fix the problem in all places, it means some un-hittable element could be tapped, that is great but some others still not.
So may I know where normalizedOffset is start, from the middle of frame to give the offset or the top left?
func forceTapElement(timeout: TimeInterval) {
if !self.waitForExistence(timeout: timeout) {
return
}
if self.isHittable {
self.tap()
} else {
let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx: 0.1, dy: 0.0))
coordinate.tap()
}
}
Add https://github.com/devexperts/screenobject as a dependency
Use .tapUnhittable() instead of .tap() for this particular view. It gets the coordinates and taps using them
I have the same situation and am looking for answers. What has worked for me was to use:
let coordinate = element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))
Still this seems like workaround for a real problem. One other strange thing is that i do not have this problem on iOS15.0 simulator, only for later versions. Currently trying with iOS15.2
One more thing I've tried is to add
.accessibilityElement(children: .combine)
and specificly telling it's a button with
.accessibility(addTraits: .isButton)
But this doesn't solve the problem.
Seems that isAccessibilityElement would be an answer here, but SwiftUI doesn't seem to have such.
I have implemented code as per the google SDK documentation line by line in my app, but still when I click on google sign in button app shifts to new view controller with webview with blank screen. Have tried multiple solution found here : GIDSignIn white screen on iOS 91. But no lucks with resolving the problem , have attached the screen shot for getting closer look about the screen.
Following are the pods that I'm using,
Running XCode 9.1, iOS 10.0 and later. Kindly request someone to help.
Update: View Hierarchy
Update: viewDidLoad's code:
GIDSignIn.sharedInstance().uiDelegate = self
if self.isChangePassword {
self.addSignInView()
}
else {
self.addSignUpView()
}
fileprivate func addSignInView() {
guard let signInEmailView: SignInEmailView = Bundle.main.loadNibNamed(NibNames.SignInEmailView.rawValue, owner: self, options: nil)?[0] as? SignInEmailView
else {
return
}
signInEmailView.delegate = self
gaManager.trackScreen(screenName: ScreenNames.SignIn.rawValue)
self.animateView(signInEmailView)
}
fileprivate func addSignInView() {
guard let signInEmailView: SignInEmailView = Bundle.main.loadNibNamed(NibNames.SignInEmailView.rawValue, owner: self, options: nil)?[0] as? SignInEmailView
else {
return
}
signInEmailView.delegate = self
gaManager.trackScreen(screenName: ScreenNames.SignIn.rawValue)
self.animateView(signInEmailView)
}
I have the same problem. I use the UIAlertView to confirm user really want to do authorization. It will show the blank screen. If I remove the UIAlertView and show the authorization view directly. It works fine.
The problem also show in the Dropbox authorization screen.
If you not use UIAlertView , please try to pass the top most controller
https://github.com/dropbox/dropbox-sdk-obj-c/issues/182
Hope this can do some help.
Finally after so many days found the problem. I was showing splash view from my appDelegate using refrence of UIWindow which was adding and removing an imgview as subview to the window. So it was somehow messing with the UINavigation's stack and my view controller was not getting any reference to the UINavigationController. After removing that code it's working just fine. Also came to the solution that, if I want to show splash screen, as I can't use UIWindow's reference, I have to add new VC and write my all navigation code there. #TedYu Thank you very much for the help. :)
Wondering if someone might help with another pair of eyes - as I am trying to work out why some of my Famo.us 'Views' are being displayed despite having an opacity StateModifier set to '0'.
Here is my code - My apologies for it not being standard - I have "Panels" instead of "Views" and a few other things..but happy to expand on the code if needed.
function _buildSidePanel() {
this._sidePanel = _createPanel.call(this);
this._sidePanel.setOptions(this.constructor.DEFAULT_OPTIONS.sideMenu);
this._sidePanel.position = this.cm(this.constructor.DEFAULT_OPTIONS.sideMenu.position);
this._container.add(this._sidePanel.position).add(this._sidePanel);
this._menuHolder = _createPanel.call(this); //My version of a View
this._menuHolder.setOptions(this.constructor.DEFAULT_OPTIONS.sideMenu.menuHolder);
// Create StateModifiers
this._menuHolder.position = this.cm({ align: [.5,.6], origin: [.5,.6], proportions: [.9,.8] });
this._menuHolder.fadeState = this.cm({ opacity: 0 });
this._menuHolder.sizeState = this.cm();
this._menuHolder.mC = new ModifierChain();
this._menuHolder.mC.addModifier(this._menuHolder.fadeState);
this._menuHolder.mC.addModifier(this._menuHolder.sizeState);
this._menuHolder.mC.addModifier(this._menuHolder.position);
/* Tried splitting it to just modifiers but getting the same thing
this._sidePanel._container.add(this._menuHolder.fadeState)
.add(this._menuHolder.sizeState)
.add(this._menuHolder.position)
.add(this._menuHolder);
*/
this._sidePanel._container.add(this._menuHolder.mC).add(this._menuHolder);
// this._menuHolder.fadeState.setOpacity(1,this.constructor.DEFAULT_OPTIONS.sideMenu.menuHolder.transition.in);
}
I have created a ModifierChain and added among other things an Opacity State of 0. When I add this and then add the modifier and 'View' to the container it displays the View even though the View has a StateModifier of '0' so should not be displayed.
The 'fadeState.setOpacity' command is meant to transition the fadeState to display the View but it is commented out, so the View should not be displayed.
I have this working in other areas so know the approach works. I am also (hopefully) not using the same variable names, so not using a StateModifier more than once. But still stuck as to why this is being displayed.
Any help or thoughts would be gratefully appreciated.
Thanks.
I'm getting started with TDD and got stuck testing a simple UITableViewController (using storyboards).
The tableView should have one row for every element in my model NSArray:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.sortedStories count];
}
My test for this is:
- (void)testTwoStoriesShouldLeadToTwoRowsInSectionZero
{
_sut.sortedStories = [self arrayWithTwoStories];
[_sut.tableView reloadData];
XCTAssertEqual([_sut tableView:_sut.tableView numberOfRowsInSection:0], 2, #"The number of rows should match the number of stories");
}
And I'm initializing my _sut in my test class from my storyboard like this:
- (void)setUp
{
[super setUp];
UIStoryboard *storyboard =
[UIStoryboard storyboardWithName:#"Main_iPhone"
bundle:nil];
_sut = [storyboard instantiateViewControllerWithIdentifier:
#"MyTableViewController"];
}
This works perfectly fine if there is no setup of the model in my production code. But after I added this default setup with seven stories in my UITableViewController's viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.sortedStories = [self sevenDefaultStories];
}
the test suddenly fails, stating that 'seven isn't equal to two'. The tableView seems not to reload the data, though I have the [_sut.tableView reloadData] in my test after changing the model.
What am I doing wrong?
I found it:
Though the tableViewController was instantiated via storyboard etc., the view had not been loaded yet!
So viewDidLoad also had not been called yet, when I 'changed' my model. But then, when I called [_sut.tableView reloadData] (which should make sure, the tableView would get synced with my model), this caused exactly the opposite: accessing the tableView made it necessary that the view got loaded, so NOW finally viewDidLoad was called on my tableViewController! And so my model got changed again, overwriting my nice test model with default values.
The solution was, to add [_sut view]; to the top of my test case. This makes sure that the view is already loaded when my test begins.
And, in my case, calling [_sut.tableView reloadData] wasn't necessary at all, since I'm only testing the dataSource method directly, not the actual tableView. N.B.:[_sut view] still needs to be called, because the dataSource method in my XCTAssertEqual() statement also triggers the view to be loaded, if that has not happened yet.
So the working test case looks like this:
- (void)testTwoStoriesShouldLeadToTwoRowsInSectionZero
{
[_sut view];
_sut.sortedStories = [self arrayWithTwoStories];
XCTAssertEqual([_sut tableView:_sut.tableView numberOfRowsInSection:0], 2, #"The number of rows should match the number of stories");
}
During test setup (my preferred solution):
[UIApplication sharedApplication].keyWindow.rootViewController = _sut; // Suck it UIKit
You may alternatively consider:
[[UIApplication sharedApplication].keyWindow addSubview:_sut.view]; // Hax
Note that UITableView may not render any cells unless it has been added to the view hierarchy. Similarly, UIViewController lifecycle methods may not be called unless it is added to the view controller hierarchy. I currently use "my preferred solution" above because it accomplishes both.
I'm rotating an instance of a CCLayer subclass like this:
[self runAction:[CCRotateBy actionWithDuration:0.5 angle:180.0]];
This rotating is in response to a user tap (which may come rapidly). How can I determine if the layer is currently being rotating? In this case I can just ignore the tap.
When declaring your CCAction, it is possible to set a tag attribute to it, and then retrieve the action by using getActionByTag. If the returning value is not nil, then it means that the action is actually running.
CCRotateBy *rotate = [CCRotateBy actionWithDuration:1.0 angle:100];
rotate.tag = 100;
[myNode runAction:rotate];
if ([myNode getActionByTag:100]) {
NSLog(#"Rotating!!");
}