注意:我在Stack Overflow上看到很多关于在Swift NSUserDefaults中重命名的帖子UserDefaults或者在重启之前没有在模拟器上工作.无论如何,这不是重复.SO标记的许多问题来自4年前.我的问题是今年特定于iOS 10的,因为它一直适用于旧版本.我已经在我的问题中提到我的问题不是那些问题的重复,因为那些是swift中的模拟器错误,我的问题是设备目标C bug.请在标记为重复之前阅读问题
我的问题不同,因为我能够在目标C和物理设备本身上重现这一点.
我从零开始为这个测试创建了一个全新的项目.我将此代码放在viewDidLoad视图控制器中:
if (![[NSUserDefaults standardUserDefaults] valueForKey:@"checkIfInitialized"]){
NSLog(@"setting checkIfInitialized as not exist");
[[NSUserDefaults standardUserDefaults] setValue:@"test" forKey:@"checkIfInitialized"];
[[NSUserDefaults standardUserDefaults] synchronize];
self.view.backgroundColor=[UIColor redColor];
self.mylabel.text=@"NSUserDefaults was NOT there, try running again";
} else {
NSLog(@"checkIfInitialized exists already");
self.view.backgroundColor=[UIColor blueColor];
self.mylabel.text=@"NSUserDefaults was already there this time, try running again";
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我运行应用程序大约10次,几次它找到了checkIfInitialized,有时它没有.没有确切的数字,它失败了多少次因为它可能会工作3次然后失败2次然后工作4次而失败一次等等.
现在事情我已经注意到(虽然肯定不是100%),这一问题似乎只当我测试通过Xcode的连接发生.如果我通过点击没有Xcode的设备上的应用程序图标启动应用程序来运行,那么它似乎工作正常,但我无法100%确定.
我注意到有时出现这个错误:
[User Defaults] Failed to write value for key checkIfInitialized in CFPrefsPlistSource<0x1700f7200> (Domain: com.xxxx.appname, User: kCFPreferencesCurrentUser, ByHost: No, Container: …Run Code Online (Sandbox Code Playgroud) 我的应用程序将文件存储在其内部存储目录(/Android/data/com.mycompany.myapp/files,由getFilesDir()返回),我希望允许用户直接从他们的文件管理应用程序访问这些文件移动设备或Android文件传输桌面应用程序.
该存储选项开发人员指南说:
默认情况下,保存到内部存储的文件对应用程序是私有的,而其他应用程序无法访问它们(用户也无法访问).
"默认情况下"意味着我可以更改默认权限以允许用户访问这些文件,但我找不到任何有关如何执行此操作的文档.当我使用文件管理应用程序浏览/ Android/data目录时,目前隐藏了com.mycompany.myapp目录.
我目前正在保存这样的文件数据:
String fileName = "myfile.jpg";
String filePath = getFilesDir() + File.separator + fileName;
FileOutputStream fileStream = new FileOutputStream(filePath);
fileData.writeTo(fileStream); // fileData is a ByteArrayOutputStream
fileStream.close();
Run Code Online (Sandbox Code Playgroud)
我尝试将各个文件的权限设置为全局可读,但这并未使目录可见:
FileOutputStream fileStream = this.app.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
Run Code Online (Sandbox Code Playgroud)
我还检查了AndroidManifest文件的文档,但没有看到任何内容.有谁知道我怎么做到这一点?
我注意到当我从iPhone主屏幕删除某个应用程序时,出现的警报视图会在左侧显示"删除"按钮,在右侧显示"取消".但是,当我使用UIAlertView在我的应用程序中构建删除功能时,按钮似乎只显示左侧的取消和右侧的删除.
我希望我的应用程序与操作系统保持一致,但我无法弄清楚如何首先显示"取消"按钮.有人知道吗?
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Delete Song"
message:@"Are you sure you want to delete this song? This will permanently remove it from your database."
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Delete", nil];
Run Code Online (Sandbox Code Playgroud)
我尝试设置alert.cancelButtonIndex = 1,但这没有任何效果.
我需要保存我的应用程序的屏幕截图,所以我设置了这样的代码,它的工作原理如下:
- (void)renderScreen {
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CGSize outputSize = keyWindow.bounds.size;
UIGraphicsBeginImageContext(outputSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CALayer *layer = [keyWindow layer];
[layer renderInContext:context];
CGContextRestoreGState(context);
UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// now save the screen image, etc...
}
Run Code Online (Sandbox Code Playgroud)
但是,当屏幕图像变得复杂(许多视图)时,在iPad 3上,renderInContext最多可能需要0.8秒,并且用户界面在此期间会锁定,这会干扰其他一些功能.所以我将渲染移动到后台线程,如下所示:
- (void)renderScreen {
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CALayer *layer = [keyWindow layer];
[self performSelectorInBackground:@selector(renderLayer:) withObject:layer];
}
- (void)renderLayer:(CALayer *)layer {
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CGSize outputSize = keyWindow.bounds.size;
UIGraphicsBeginImageContext(outputSize);
CGContextRef context = UIGraphicsGetCurrentContext(); …Run Code Online (Sandbox Code Playgroud) 我有一些UTF-8内容,包括多字节智能引号字符.我发现这段代码很容易将这些字符转换成ASCII直引号(ASCII码34):
$content = iconv("UTF-8", "ASCII//TRANSLIT", $content);
Run Code Online (Sandbox Code Playgroud)
要么
$content = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $content);
Run Code Online (Sandbox Code Playgroud)
但是,我宁愿将它们转换为扩展的ASCII智能引号(拉丁语1编码中的ASCII代码147和148).有谁知道如何做到这一点?
我正在使用手势检测器从滚动视图捕获滚动事件:
val gestureDetector = GestureDetector(this.fragment.activity, ScrollGestureListener(scrollView))
scrollView.setOnTouchListener(OnTouchListener { view, event ->
gestureDetector.onTouchEvent(event)
return@OnTouchListener false
})
internal inner class ScrollGestureListener(view: View) : GestureDetector.SimpleOnGestureListener() {
override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
this@DocumentViewer.onDrag()
return true
}
}
Run Code Online (Sandbox Code Playgroud)
当使用compileSdkVersion 30时,我的应用程序会在onScroll函数上崩溃,因为它总是收到第一个参数的空值。我通过将第一个参数设为可选来解决这个问题:
override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
Run Code Online (Sandbox Code Playgroud)
现在我尝试将compileSdkVersion更新为33,上面的行将不再编译。但是,如果我恢复到标准函数签名,那么当我滚动滚动视图时应用程序会再次崩溃。
这篇 SO 帖子的评论说:“如果手势检测器以外的其他东西消耗了 ACTION_DOWN 事件,你就会遇到这样的崩溃。” 但我不知道还能做什么。我在此片段中的其他一些视图上有手势检测器,但如果我注释掉所有这些代码,崩溃仍然存在。
onDown我暂时添加了一个实现ScrollGestureListener,但它从未被调用,因此这似乎与 ACTION_DOWN 注释有关。
查看 的源代码GestureDetector.java,我发现它发送到的第一个参数onScroll是mCurrentDownEvent,因此这似乎也与 ACTION_DOWN 注释相关。但如果我 …
我有一个Xcode 4项目,它构建了两个不同的目标.我已经在构建设置中定义了一些常量,因此我可以为每个目标运行不同的代码,如下所示:
#ifdef VERSION1
// do this
#else
// do that
#endif
Run Code Online (Sandbox Code Playgroud)
在应用程序的一个版本中,我需要主视图控制器打开另一个视图控制器并成为其委托,但另一个版本不使用该视图控制器,不应编译其代码或尝试成为其委托.我已经设置了主视图控制器头像这样:
#ifdef VERSION2
#import "SpecialViewController.h"
#endif
@interface MainViewController : UIViewController <MPMediaPickerControllerDelegate, SpecialViewControllerDelegate> {
// etc.
Run Code Online (Sandbox Code Playgroud)
围绕#import标签的条件工作正常,但是如何在一个版本中将此类声明为SpecialViewControllerDelegate而不是另一个版本?
我在UIWebView中显示文档.我想在文档上放置一个热点以在触发时触发操作,但我还想保持默认的UIWebView在双击时自动缩放文档的行为.在让UIWebView响应双击时,我无法弄清楚如何响应单击.
我首先将热点设置为带有动作的透明UIButton,但是双击热点导致热点动作被调用两次.所以我从按钮中删除了操作并附加了单击手势:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
singleTap.numberOfTapsRequired = 1;
singleTap.delegate = self;
[self.hotspot addGestureRecognizer:singleTap];
[singleTap release];
Run Code Online (Sandbox Code Playgroud)
这与普通按钮操作相同.但后来我创建了一个双击手势,并将其配置为阻止使用requireGestureRecognizerToFail的单击手势:
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomWebView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
[self.hotspot addGestureRecognizer:doubleTap];
[doubleTap release];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction:)];
singleTap.numberOfTapsRequired = 1;
[singleTap requireGestureRecognizerToFail:doubleTap];
singleTap.delegate = self;
[self.hotspot addGestureRecognizer:singleTap];
[singleTap release];
- (void)zoomWebView:(UITapGestureRecognizer *)gesture {
NSLog(@"double tap");
}
Run Code Online (Sandbox Code Playgroud)
通过此设置,单击热点调用singleTapAction,双击热点调用zoomWebView(自定义方法).这很好,因为singleTapAction不再被调用两次,但是因为UIWebView不再响应双击而不好.
我尝试通过继承UITapGestureRecognizer,将双击事件从我的doubleTap手势转发到UIWebView,覆盖touchesBegan和touchesEnded方法,并将其参数发送到UIWebView的相应方法.当我这样做时,我可以看到我的子类正在接收事件,但UIWebView没有响应转发的事件.这是可以预料到的,因为iOS的事件处理指南说我们只能将事件转发到UIView的自定义子类,而不是UIKit框架对象.
有没有办法阻止我的单击手势响应不会转移双击事件的双击?这似乎是一个基本要求,但我看不到一种直接的方法.我阅读并试验了UIGestureRecognizer的触摸传递属性,但没有值的组合阻止单击手势消耗双击手势.
顺便说一下,我的视图层次结构中热点和UIWebView之间的关系是"堂兄弟" - 它们是两个兄弟视图的子视图.如果我将手势识别器添加到热点视图,Web视图或其"祖父母"视图,我会得到相同的结果.
我第一次尝试提交 Mac Catalyst 应用程序,但上传始终失败,并显示以下错误消息:
错误 ITMS-90283:“配置文件无效。捆绑包 maccatalyst.com.arlomedia.setlistmaker [maccatalyst.com.arlomedia.setlistmaker.pkg/Payload/SetListMaker.app] 中包含的配置文件无效。[无效的 'com.apple .application-identifier' 权利值。] 有关更多信息,请访问 macOS 开发人员门户。”
如果我手动或自动签署应用程序,就会发生这种情况。通过手动签名,我拥有了一个新的 macOS App Store 配置文件,该配置文件是使用关联的 iOS 应用程序 ID 作为 Mac Catalyst 配置文件创建的。这在配置门户中显示为有效,我可以使用所选的配置文件构建(存档)应用程序:
当我在 Xcode 管理器中完成提交过程时,我每次都必须“导入”配置文件(我下载了配置文件,只需在此处选择下载的文件),这很奇怪:
但是选择文件后,我可以单击其信息图标,一切看起来都是正确的:
然后我继续上传,当进度条到达末尾时,出现错误,提交失败。
错误消息表明应用程序标识符有问题,但我已经检查了所有可以找到它的地方,它看起来是正确的。我正在使用自动派生的捆绑包 ID,它将“maccatalyst”前缀添加到我的 iOS 捆绑包 ID 上。在某些显示此信息的地方,ID 还以配置门户中应用程序标识符记录中的应用程序 ID 前缀为前缀。上面的屏幕截图显示了 App ID 的最后一个字母被截断,但我认为这只是 Xcode 中的显示;如果我打开配置文件,则会列出完整的 ID。
我同时正在开发另一个应用程序,并且我能够成功提交它。我打开了两个项目的存档 .app 文件,并比较了嵌入式配置文件,唯一的区别是我所期望的,例如应用程序名称和导出时间。应用程序标识符和捆绑包 ID 的格式相同,并具有正确的应用程序前缀。我还比较了两个应用程序的 info.plist 文件,也没有发现任何显着差异。另一个应用程序还要求我在提交过程中选择配置文件,所以这似乎不是问题(尽管在我的 iOS 提交中,配置文件名称会自动显示在那里)。
当我打开自动签名时,会跳过一些上传步骤,但在上传结束时收到相同的错误消息。如果我在 Xcode 管理器中使用“验证应用程序”按钮而不是“分发应用程序”按钮,我将执行相同的步骤并收到相同的错误消息。
我比较了两个应用程序的应用程序 ID 和配置文件的设置、签名设置、构建设置、iTunes Connect 中的应用程序信息页面……所有内容都以相同的方式设置。有谁知道我还应该检查什么?
我正在尝试通过HTML5 FileReader在Web浏览器中选择本地JPEG文件,因此我可以将其提交到服务器而无需重新加载页面.所有的机制都在工作,我想我正在传输和保存JavaScript给我的确切数据,但结果是服务器上的JPEG文件无效.这是演示此问题的基本代码:
<form name="add_photos">
?<input type=?"file" name=?"photo" id=?"photo" /><br />
?<input type=?"button" value=?"Upload" onclick=?"upload_photo()?;?" />?
</form>
<script type="text/javascript">
function upload_photo() {
file = document.add_photos.photo.files[0];
if (file) {
fileReader = new FileReader();
fileReader.onload = upload_photo_ready;
fileReader.readAsBinaryString(file);
}
}
function upload_photo_ready(event) {
data = event.target.result;
// alert(data);
URL = "submit.php";
ajax = new XMLHttpRequest();
ajax.open("POST", URL, 1);
ajax.setRequestHeader("Ajax-Request", "1");
ajax.send(data);
}
</script>
Run Code Online (Sandbox Code Playgroud)
然后我的PHP脚本执行此操作:
$data = file_get_contents("php://input");
$filename = "test.jpg";
file_put_contents($filename, $data);
$result = imagecreatefromjpeg($filename);
Run Code Online (Sandbox Code Playgroud)
最后一行抛出PHP错误"test.jpg不是有效的JPEG文件".如果我将数据下载回我的Mac并尝试在预览中打开它,预览说文件"可能已损坏或使用预览无法识别的文件格式".
如果我打开桌面上的原始文件和文本编辑器中服务器上的上传文件来检查它们的内容,它们几乎可以完全不同.原始文件如下所示:
?ÿ?‡JFIF??;CREATOR: gd-jpeg v1.0 (using IJG JPEG …Run Code Online (Sandbox Code Playgroud) ios ×5
android ×2
ios4 ×2
objective-c ×2
xcode ×2
app-store ×1
calayer ×1
delegates ×1
filereader ×1
gesture ×1
hig ×1
html5 ×1
iconv ×1
ios10 ×1
ios5 ×1
iphone ×1
javascript ×1
kotlin ×1
mac-catalyst ×1
php ×1
uialertview ×1
uikit ×1
uiwebview ×1