自升级到XCode8 GM和ios10以来,通过Interface Builder创建的所有视图都没有正确初始化,直到比预期要晚得多.这意味着在viewDidLoad,cellForRowAtIndexPath,viewWillAppear等中,每个视图的帧大小都设置为{1000,1000}.在某些时候他们似乎是正确的,但它为时已晚.
遇到的第一个问题是全面的角落圆角失败:
view.layer.cornerRadius = view.frame.size.width/2
Run Code Online (Sandbox Code Playgroud)
对于依赖于帧大小在代码中进行计算的任何事情,都会出现进一步的问题.
cellForRowAtIndexPath
Run Code Online (Sandbox Code Playgroud)
对于cellForRowAtIndexPath,帧大小在初始表显示时失败,但滚动后它可以正常工作.willDisplayCell:forRowAtIndexPath也没有正确的帧大小.
我已经对一些值进行了硬编码,但显然这是非常糟糕的代码实践,在我的项目中也是如此.
有没有办法或地方获得正确的框架尺寸?
编辑
我发现使用高度/宽度约束而不是帧宽高度更可靠.这可能会增加需要大量新IBOutlet的开销,以链接项目的高度/宽度约束.
现在我已经创建了一个UIView类,它允许我在没有IBOutlets的情况下直接访问View的高度/宽度约束.对于最小的使用,小循环不应该是一个大问题.对于没有明显创建宽度/高度约束的IB项目,不能保证结果.可能最好为常数返回0,或者更糟.此外,如果您没有高度/宽度约束,并且您的视图基于前导/尾随约束动态调整大小,则这将不起作用.
-viewDidLoad似乎具有正确的帧大小,但如果您在此处进行修改,通常会导致UI的可视更改.
UIView的+ WidthHeightConstraints.h
@interface UIView (WidthHeightConstraints)
-(NSLayoutConstraint*)widthConstraint;
-(NSLayoutConstraint*)heightConstraint;
-(NSLayoutConstraint*)constraintForAttribute:(NSLayoutAttribute)attribute;
@end
Run Code Online (Sandbox Code Playgroud)
UIView的+ WidthHeightConstraints.m
#import "UIView+WidthHeightConstraints.h"
@implementation UIView (WidthHeightConstraints)
-(NSLayoutConstraint*)widthConstraint{
return [self constraintForAttribute:NSLayoutAttributeWidth];
}
-(NSLayoutConstraint*)heightConstraint {
return [self constraintForAttribute:NSLayoutAttributeHeight];
}
-(NSLayoutConstraint*)constraintForAttribute:(NSLayoutAttribute)attribute {
NSLayoutConstraint *targetConstraint = nil;
for (NSLayoutConstraint *constraint in self.constraints) {
if (constraint.firstAttribute == attribute) {
targetConstraint = constraint;
break;
}
}
return targetConstraint;
}
@end
Run Code Online (Sandbox Code Playgroud)
编辑2
事实证明,上述类别只是部分有效.主要是因为ios似乎自动添加一些额外的高度/宽度约束重复项,类型为NSContentSizeLayoutConstraint,实际上与普通约束的大小不同.NSContentSizeLayoutConstraint也是一个私有类,所以我不能做isKindOfClass来过滤掉那些.我还没有找到另一种有效测试的方法.这很烦人.
我使用UITableView来呈现各种viewControllers.根据单击的索引,它将显示一个不同的视图控制器,然后可以将其解除.出于某种原因,我的一个ViewControllers需要两次点击才能显示.因此,似乎每个其他点击都有效.其他视图演示工作正常,所以表可能没问题.
我在ViewController中看到的即将显示的是,在第一次单击时,它通过didSelectRowAtIndexPath进行,然后在目标视图中触发:ViewWillLoad,ViewLoaded,ViewWillAppear ....但不是ViewDidAppear.在第二次单击时,只有ViewDidAppear会在显示时触发.在第二次单击时,它甚至没有通过didSelectRowAtIndexPath.此外,我可以第二次点击屏幕上的任意位置,它将显示.
它将继续来回执行此操作,似乎只显示每隔一次点击的目标视图.有没有想过为什么会这样?
/* RightPanelViewController */
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch(indexPath.row){
case 0:
// this view takes two clicks to display
[self presentViewController:self.delegateRef.savedRidesViewController animated:YES completion:nil];
break;
case 1:
// this works fine, as do others
[self presentViewController:self.delegateRef.sensorsViewController animated:YES completion:nil];
break;
case 2:
...
}
/* savedRidesViewController */
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
Run Code Online (Sandbox Code Playgroud) 当我尝试将应用程序提交上传到我所属的组织上的itunes connect时,我收到了所声明的错误,但是itunes it username与我的Apple开发者ID不同.
问题是我有一个Apple Developer ID,我用于跨多个组织的所有IOS开发.my.name@gmail.com该ID已添加到IOS成员中心的多个组织中.但是,在Itunes Connect上,它不允许您作为组织的新用户添加现有Apple ID(或不同组织上的现有Itunes Connect用户).
因此,如果我是3个组织的成员,每个人都使用不同的Itunes Connect电子邮件,通常是该组织的电子邮件,而不是我的主要Gmail Apple ID.
尝试使用XCode上传时,我收到此错误,因为它们不匹配.我该如何解决这个问题?我只使用与他的appleID + itunes用户匹配的同事ID来为一个组织修复它.但是我希望能够自己做.
我尝试将个人组织电子邮件添加为xcode电子邮件,但它们都不是Apple Developer帐户,Xcode拒绝使用它们.
如何将我的应用程序上传到新的组织我是Itunes connect的成员?
编辑
我尝试使用Xcode菜单中的Application Loader工具,我得到了如下所示的不同类型的错误.我尝试使用App Store Build和Ad Hoc构建.这是一个开发版本,我希望通过Itunes Connect Testflight用于内部测试,所以我们还没有使用Release/AppStore配置文件,我们甚至还没有创建它们.
编辑2
Apple文档说:
"单个Apple ID可以与多个会员中心团队相关联.使用相同的Apple ID,您可以作为个人注册并加入其他团队.但是,您只能与单个iTunes Connect团队关联.因此,开发人员应该创建另一个Apple ID,用于他们想要在iTunes Connect中单独管理的不同个人或公司帐户."
itunes连接也是如此.但是,如何从xcode向其他itunes连接帐户提交构建?
我正在进行UI单元测试,并且几天后UI单元测试拒绝正常启动.我设置了一个简单的测试来点击一个按钮,当我运行它时,它会在启动测试之前挂起启动应用程序.
注意,它总是挂起一分钟,然后正确地进行测试.
如果我从模拟器设备中删除应用程序,或清除整个模拟器的内容和设置,则测试会在第一次运行时立即成功运行.它每次都会挂起,直到我再次删除.这也不是很好,因为我最终每次都会收到新的位置批准提示,这可能会干扰应用程序.
这里发生了什么?
t = 0.00s Start Test
t = 0.00s Set Up
t = 0.00s Launch com.domain.appName
2015-10-06 11:59:24.493 XCTRunner[66707:4085844] Continuing to run tests in the background with task ID 1
t = 0.92s Waiting for accessibility to load
t = 60.92s Wait for app to idle
... rest of test runs immediately
Run Code Online (Sandbox Code Playgroud) 我正在启动Apple Pay集成项目,并且能够在设备上连接交易,并使用Stripe授权付款.我实际上正在努力的部分是设备测试Apple Pay是否受支持的正确方法?因此,对于较旧的Iphone型号,我会选择隐藏Apple Pay功能,即使它们安装了ios8或ios9.
我可以检查设备型号,然后忽略Apply Pay for <Iphone5S.然而,如果我还需要开始测试IPad版本等,这会变得复杂.
我想知道是否有一种方法可以测试ApplePay是否受支持?
我在网上发现这种方法是一个想法,但是它声称在Iphone5模拟器中支持苹果支付,我想这并不完全正确.不幸的是,我没有Iphone5实际设备进行测试.
- (BOOL) applePaySupported {
return [PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkAmex, PKPaymentNetworkVisa, PKPaymentNetworkMasterCard]];
}
Run Code Online (Sandbox Code Playgroud)
编辑/解决方案:
我现在使用这一行,它被验证适用于Iphone5(不支持)与Iphone6(支持); 我推测其他设备.我不完全确定它总是在模拟器中工作,但ApplePay在那里有点奇怪,测试最好在设备上完成.
- (BOOL) applePaySupported {
return [PKPaymentAuthorizationViewController canMakePayments] && [PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkAmex, PKPaymentNetworkVisa, PKPaymentNetworkMasterCard]];
}
Run Code Online (Sandbox Code Playgroud) 我一直在研究新的M7芯片CMMotionActivityManager
,用于确定设备的用户是在走路,跑步,在汽车等等(参见Apple文档).这似乎是尝试LocationManager
仅使用和加速计数据来确定此前一步的一大进步.
然而,我注意到CMMotionActivityManager
没有自行车活动,这是令人失望的,并且几乎是一个完全用作新活动经理的交易破坏者.有没有其他人找到一个方便的方式CMMotionActivityManager
与骑自行车一起使用,而不必重新加入CMLocationManager
+加速度计只是为了尝试测试骑自行车?
请注意,这也不包括像火车这样的东西的一般运输选项.例如,我每天在火车上上班一小时.汽车可以至少更加通用,类似于Move使用Transport的方式.
CMMotionActivity
仅具有以下定义的运动类型:
来自Apple代码的有用说明,不一定能解决问题,但有用:
CMMotionActivity
基于设备的运动估计用户的活动.
活动作为一组属性公开,属性不是互斥的.
例如,如果您在停车标志处停车时状态可能如下:固定=是,行走=否,运行=否,汽车=是
或移动车辆,静止=否,行走=否,运行=否,汽车=是
或者设备可以运动但不能行走或在车辆中.静止=否,行走=否,运行=否,汽车=否.请注意,在这种情况下,所有属性都是NO.
[直接来源:Apple iOS Framework,CoreMotion/CMMotionActivity.h @interface CMMotionActivity,内联代码注释]
今天我通过Xcode向应用程序商店提交了一个新的测试应用程序,以便在ItunesConnect中查看.该应用程序已成功提交,但二进制文件在大约一分钟后被ITC拒绝.AppIcons在PNG中有alpha通道时出现问题.我得到了很多.
我注意到的问题是我收到了来自ITC的电子邮件通知,并且该电子邮件被发送到我们实体的整个用户列表.这意味着我们所有应用程序中的所有ITC测试飞行用户.为了添加测试航班用户,需要在"用户和角色"中进行设置,并且通常会给出"销售/市场营销"这样的任意角色.(为什么没有专门针对试飞用户的角色?).我尝试为他们关闭通知,但设置似乎有限.
最后,所有这些用户都会收到这个新测试应用程序的通知,这些应用程序从未关联过,也不应该关注.此应用程序未启用TestFlight,但这似乎与此无关.
有没有办法阻止整个用户列表收到技术电子邮件错误等完全不相关的应用程序?
我尝试在相关通知部分中禁用通知,但它非常模糊,似乎不相关.它没有帮助.
我正在尝试设置一个UIPageViewController
可以通过NSUrlConnection
数据拉动动态加载页面视图无限滚动.我从3个观点开始:prev,curr,next; 并在到达pageData
阵列中的第一个或最后一个视图时加载其他视图.
麻烦的是我在viewControllerBeforeViewController
或中加载了其他视图viewControllerAfterViewController
.在页面之间进行单次滑动时,似乎可以调用这些方法2-3次.它们也可以在从不完成页面转换的半滑动期间调用.这可能意味着多个预加载开始过早完成.然后不知何故pageViewController
忘记了当前的位置.
[self.pageViewController setViewControllers:@[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:NO completion:nil];
Run Code Online (Sandbox Code Playgroud)
下面使用此行来表示添加数据pageViewController
,并转到适当的视图.当我开始使用它时,它不是通过滑动进入上一个/下一个视图,而是开始跳转到看似随机的视图.一旦我开始前进向后滑动......
是否有更合适的地方进行预加载,仅在页面转换完成后调用一次?并且,是否必须调用上面的行,或者是否有更可靠的方法来确保它进入正确的页面?感到很沮丧试图在这里连线.
// the init line, somewhere early on. uses Scoll style
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationVertical options:nil];
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self.pageData indexOfObject:viewController];
if(index == 1){
// if loading last one on start, preload one more in advance
[self loadSecondaryCalData:-1 endView:[[self viewControllerAtIndex:index-1] retain]];
} else if ((index == 0) …
Run Code Online (Sandbox Code Playgroud) 我有一个基本的watchkit应用程序,可以加载基于页面的3个界面控制器导航.这很好用,但我想触发一个动作来删除页面控件,并基本上恢复到应用程序第一次加载时出现的原始InterfaceController.
// load page based control, with 3 views. this works ok
[WKInterfaceController reloadRootControllersWithNames:@[@"pageController1",@"pageController2",@"pageController3"]
contexts:@[@"data1",@"data2",@"data3"]];
// attempt to reload original interface controller, identified by storyboard id
[WKInterfaceController reloadRootControllersWithNames:@[@"myInterfaceController"] contexts:@[@{}]];
Run Code Online (Sandbox Code Playgroud)
基于页面的导航删除,原始导航在短微调器后加载.但是它无法正常运行,原始操作会导致此错误.
Extension[6766:123665] *********** ERROR
-[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来干净地重新加载原始的InterfaceController?
编辑,2/19
似乎还有一些其他操作也会导致此错误.例如,如果segue到第二个InterfaceController然后popController返回,则经常出现错误.它始终与此函数的辅助调用相关.
[WKInterfaceController reloadRootControllersWithNames: contexts:]
Run Code Online (Sandbox Code Playgroud)
EDIT2,3/18
如前所述,通过执行seguePush,popController,然后尝试reloadRootControllersWithNames,这可以100%重现.
如果事先没有完成seguePush/popController,那么reloadRootControllersWithNames将正常工作.
这种情况似乎是这个bug的多个>单个多实例的补充.
我正在使用ios钥匙串(keychainItemWrapper
/ SSKeychain
)来存储我的应用程序的登录令牌并保持登录状态.目前,我NSDictionary
在包含我的令牌,令牌到期和刷新令牌的钥匙串中存储了一个简单的内容.我将它序列化为NSData并使用存储kSecValueData
.我还设置了kSecAttrAccount
和kSecAttrService
,但不使用那些权威性.
这种方法效果很好,大约95%的时间都是如此.问题是随机,不可预测和零星地,当我请求它来检索令牌时,钥匙串不会返回数据.通常在距离应用程序适度的时间之后重新打开它.它不一定是在后台,也不是在任何特定的延迟之后.
询问我当它具体失败NSData
的下方,返回<>
来代替<ABCD EFGH IJKL ....>
.我认为这是零.因此,代码认为用户未登录并立即将其丢弃在我的应用程序的注册/登录登录页面上,没有注销错误,令牌到期错误等.如果我最小化应用程序,然后重新打开,它几乎总是获得正确的钥匙串信息和用户再次登录.
遇到这会产生令人困惑的体验.这也意味着用户无法保持这种真正的100%登录状态,偶尔会被随机注销.我一直无法预测或调试它,更改钥匙串库,如下所示,并没有为我修复它.它适用于我和几个TestFlight用户,以及我们目前的生产应用程序.
有关如何维护钥匙串完整性和加载100%时间的任何建议?我们准备在令牌上实现NSUserDefaults备份存储,以便在这些情况下使用,我真的不想这样做来存储身份验证令牌.
储存:
// load keychain
KeychainItemWrapper *keychainItem = [KeychainItemWrapper keyChainWrapperForKeyID:kcIdentifier];
NSString *firstLaunch = [keychainItem objectForKey: (__bridge id)(kSecAttrAccount)];
if (firstLaunch == nil){
// initialize if needed
[keychainItem setObject:email forKey: (__bridge id)(kSecAttrAccount)];
[keychainItem setObject:kcIdentifier forKey: (__bridge id)kSecAttrService];
[keychainItem setObject:(id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
}
// serialize "auth" NSDictionary into NSData and store
NSString *error;
NSData *dictionaryData = [NSPropertyListSerialization dataFromPropertyList:auth format:NSPropertyListXMLFormat_v1_0 …
Run Code Online (Sandbox Code Playgroud) ios ×7
objective-c ×3
xcode ×2
apple-m7 ×1
applepay ×1
autolayout ×1
core-motion ×1
frame ×1
ios10 ×1
iphone ×1
keychain ×1
sskeychain ×1
uitableview ×1
unit-testing ×1
watchkit ×1
xcode7 ×1
xcode8 ×1